package com.hskn.hss.module.kfkdeal.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hskn.hss.constant.CommonConstant;
import com.hskn.hss.entity.AbnormalResult;
import com.hskn.hss.exception.HssException;
import com.hskn.hss.module.alarmcar.entity.AlarmCar;
import com.hskn.hss.module.alarmcar.mapper.AlarmCarMapper;
import com.hskn.hss.module.alarmsheshi.entity.AlarmSheshi;
import com.hskn.hss.module.alarmsheshi.mapper.AlarmSheshiMapper;
import com.hskn.hss.module.carPlan.entity.CarPlan;
import com.hskn.hss.module.carPlan.mapper.CarPlanMapper;
import com.hskn.hss.module.carPlanCollectPoint.entity.CarPlanCollectPoint;
import com.hskn.hss.module.carPlanCollectPoint.mapper.CarPlanCollectPointMapper;
import com.hskn.hss.module.carTrack.entity.CarTrack;
import com.hskn.hss.module.carTrack.mapper.CarTrackMapper;
import com.hskn.hss.module.carTrack.service.CarTrackService;
import com.hskn.hss.module.carTrack.to.MileageAndOilWearTo;
import com.hskn.hss.module.carTrack.vo.MileageAndOilWearVo;
import com.hskn.hss.module.carTrackOriginal.entity.CarTrackOriginal;
import com.hskn.hss.module.carTrackOriginal.service.CarTrackOriginalService;
import com.hskn.hss.module.carviolation.entity.CarViolation;
import com.hskn.hss.module.carviolation.mapper.CarViolationMapper;
import com.hskn.hss.module.depart.entity.SysDepart;
import com.hskn.hss.module.depart.mapper.SysDepartMapper;
import com.hskn.hss.module.employeePunchCard.service.EmployeePunchCardService;
import com.hskn.hss.module.grid.entity.Grid;
import com.hskn.hss.module.grid.service.IGridService;
import com.hskn.hss.module.kfkcarlocation.entity.KfkCarLocation;
import com.hskn.hss.module.kfkcarlocation.mapper.KfkCarLocationMapper;
import com.hskn.hss.module.kfkdeal.entity.car.KfkHandleParam;
import com.hskn.hss.module.kfkdeal.entity.car.kfkDealCarWorkPlan;
import com.hskn.hss.module.kfkmanholecover.entity.KfkManholeCover;
import com.hskn.hss.module.oilDevice.domain.StateOilDevice;
import com.hskn.hss.module.role.entity.SysRole;
import com.hskn.hss.module.role.mapper.SysRoleMapper;
import com.hskn.hss.module.rptCarWork.entity.RptCarWork;
import com.hskn.hss.module.rptCarWork.mapper.RptCarWorkMapper;
import com.hskn.hss.module.tlcar.entity.TlCar;
import com.hskn.hss.module.tlcar.mapper.TlCarMapper;
import com.hskn.hss.module.tlcarmodel.entity.TlCarModel;
import com.hskn.hss.module.tlcarmodel.mapper.TlCarModelMapper;
import com.hskn.hss.module.tlcartype.entity.TlCarType;
import com.hskn.hss.module.tlcartype.service.ITlCarTypeService;
import com.hskn.hss.module.tlemergentplan.entity.TlEmergentPlan;
import com.hskn.hss.module.tlemergentplan.mapper.TlEmergentPlanMapper;
import com.hskn.hss.module.tlemployee.entity.TlEmployee;
import com.hskn.hss.module.tlemployee.mapper.TlEmployeeMapper;
import com.hskn.hss.module.tlequip.entity.TlEquip;
import com.hskn.hss.module.tlequip.mapper.TlEquipMapper;
import com.hskn.hss.module.tlfacilities.entity.TlFacilities;
import com.hskn.hss.module.tlfacilities.mapper.TlFacilitiesMapper;
import com.hskn.hss.module.tlthreshold.entity.TlThreshold;
import com.hskn.hss.module.tlthreshold.service.ITlThresholdService;
import com.hskn.hss.module.user.entity.User;
import com.hskn.hss.module.user.mapper.UserMapper;
import com.hskn.hss.module.userrole.entity.SysUserRole;
import com.hskn.hss.module.userrole.mapper.SysUserRoleMapper;
import com.hskn.hss.module.workkaoqin.entity.WorkKaoqin;
import com.hskn.hss.module.workrule.entity.WorkRule;
import com.hskn.hss.module.workrule.mapper.WorkRuleMapper;
import com.hskn.hss.module.workruleitem.entity.WorkRuleItem;
import com.hskn.hss.module.workruleitem.mapper.WorkRuleItemMapper;
import com.hskn.hss.utils.*;
import com.hskn.hss.utils.PerformanceMonitor.PerformanceMonitor;
import com.hskn.hss.utils.redis.RedisUtil;
import com.hskn.hss.utils.redis.key.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Slf4j
@Service
public class KfkHandleServiceImpl {
    @Autowired
    LocationUtils locationUtil;
    @Autowired
    WorkUtil workUtil;
    @Resource
    CarTrackMapper carTrackMapper;
    @Autowired
    CarTrackService carTrackService;
    @Resource
    WorkRuleMapper workRuleMapper;
    @Resource
    WorkRuleItemMapper workRuleItemMapper;
    @Resource
    TlEquipMapper tlEquipMapper;
    @Resource
    KfkCarLocationMapper kfkCarLocationMapper;
    @Resource
    TlEmergentPlanMapper tlEmergentPlanMapper;
    @Resource
    private TlCarMapper tlCarMapper;
    @Resource
    private TlCarModelMapper tlCarModelMapper;
    @Resource
    private AlarmCarMapper alarmCarMapper;
    @Resource
    private CarViolationMapper carViolationMapper;
    @Resource
    private RptCarWorkMapper rptCarWorkMapper;
    @Resource
    private KfkDealServiceImpl kfkDealService;
    @Resource
    private TlEquipMapper equipMapper;
    @Resource
    private TlFacilitiesMapper facilitiesMapper;
    @Resource
    private AlarmSheshiMapper alarmSheshiMapper;
    @Resource
    private TlFacilitiesMapper tlFacilitiesMapper;
    @Resource
    private ITlCarTypeService tlCarTypeService;
    @Resource
    private ITlThresholdService tlThresholdService;
    @Resource
    private IGridService iGridService;
    @Resource
    private SysDepartMapper sysDepartMapper;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;
    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private TlEmployeeMapper tlEmployeeMapper;
    @Resource
    private CarPlanMapper carPlanMapper;
    @Resource
    private CarPlanCollectPointMapper carPlanCollectPointMapper;
    @Resource
    private CarTrackOriginalService carTrackOriginalService;
    @Resource
    private EmployeePunchCardService employeePunchCardService;

    public void carLocationHandle(Map value, Date kfkTime) {
        Boolean isInsert = true;
        long carSTime1 = System.currentTimeMillis();
        KfkHandleParam kfkHandleParam = setKfkHandleParam(value);
        kfkHandleParam.setCarTrackId(StringUtils.uuid());
        kfkHandleParam.setKfkTime(kfkTime);

        //数据初始化
        KfkCarLocation kfkCarLocation = initKfkCarLocation(kfkHandleParam);
        //数据初始化
        CarTrack currentCarTrack = initCarTrack(kfkHandleParam);

        AbnormalResult abnormalResult = new AbnormalResult();
        try {
            QueryWrapper<TlEquip> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TlEquip::getEquipcode, kfkHandleParam.getEqpnum());
            TlEquip tlEquip = tlEquipMapper.selectOne(queryWrapper);
            if (null == tlEquip) {
                log.error("==carLocationHandle,设备不存在，设备编号：{}", kfkHandleParam.getEqpnum());
                throw new RuntimeException("设备不存在，设备编号：" + kfkHandleParam.getEqpnum());
            }
            TlCar tlCar = tlCarMapper.selectById(tlEquip.getBindobjid());
            if (null == tlCar) {
                log.error("==carLocationHandle,车辆不存在，车辆ID：{},设备编号:{}", tlEquip.getBindobjid(), tlEquip.getEquipcode());
                throw new RuntimeException("车辆不存在，车辆ID：" + tlEquip.getBindobjid() + ",设备编号:" + tlEquip.getEquipcode());
            }
            SysDepart sysDepart = sysDepartMapper.selectById(tlCar.getDeptid());
            if (Objects.nonNull(sysDepart)) {
                tlCar.setCardeptname(sysDepart.getDepartName());
            }
            //1
            setTlCarAndKfakHandle(tlCar, kfkHandleParam);
            //2
            kfkCarLocation.setCarnum(tlCar.getCarnumber());
            kfkCarLocation.setCarid(tlCar.getId());
            kfkCarLocation.setCartype(tlCar.getCartypeid());
            kfkCarLocation.setCardeptid(tlCar.getCardeptid());
            //3
            currentCarTrack.setCarnumber(tlCar.getCarnumber());
            currentCarTrack.setCarId(tlCar.getId());
            currentCarTrack.setOilMass(new BigDecimal(NumberUtil.decimalFormat("00.00", kfkHandleParam.getOilPercent() * kfkHandleParam.getOilBox())));
            kfkHandleParam.setCurrentCarTrack(currentCarTrack);

            //该车辆永久最后一条轨迹数据
            CarTrack preCarTrack = RedisUtil.get(CarTrackLastOneKey.token, currentCarTrack.getCarId(), CarTrack.class);
            if (Objects.isNull(preCarTrack)) {
                preCarTrack = setPreCarTrack(tlCar, currentCarTrack);
            }
            kfkHandleParam.setPreCarTrack(preCarTrack);
            if (currentCarTrack.getTimestamp().equals(preCarTrack.getTimestamp()) && currentCarTrack.getCarId().equals(preCarTrack.getCarId()) && currentCarTrack.getLocation().equals(preCarTrack.getLocation())
                    && currentCarTrack.getOilMass().equals(preCarTrack.getOilMass()) && currentCarTrack.getSpeed().equals(preCarTrack.getSpeed()) && currentCarTrack.getMileage().equals(preCarTrack.getMileage())) {
                isInsert = false;
                return;
            }


            // 计算当前坐标和上一次坐标的距离
            Double towPointDistance = locationUtil.getDistance(kfkHandleParam.getLat(), kfkHandleParam.getLon(), kfkHandleParam.getPreCarTrack().getLat(), kfkHandleParam.getPreCarTrack().getLng());
            kfkHandleParam.setTwoPointDistanceDiffer(towPointDistance);
            // 两坐标点距离
            currentCarTrack.setDistanceBetween(towPointDistance.intValue());

            Integer secondTimeDiffer = getTwoPointDifferTime(preCarTrack, currentCarTrack);
            kfkHandleParam.setTwoPointTimeDiffer(secondTimeDiffer);

            /**
             * 4 报警处理
             */
            abnormalResult = setKfkHandleAndCarTrack(kfkHandleParam, preCarTrack, currentCarTrack);

            long carSTime2 = System.currentTimeMillis();
            log.info("=====carLocationHandle1=执行时间(毫秒)：{}", carSTime2 - carSTime1);

            List<Grid> gridList = iGridService.list();
            Map<String, Grid> gridMap = gridList.stream().collect(Collectors.groupingBy(Grid::getGridId, Collectors.collectingAndThen(Collectors.toList(), grids -> grids.get(0))));
            List<kfkDealCarWorkPlan> workPlanList = workPlanList(tlCar, kfkHandleParam);
            long carSTime3 = System.currentTimeMillis();
            log.info("=====carLocationHandle2=执行时间(毫秒)：{}", carSTime3 - carSTime2);
            for (kfkDealCarWorkPlan inWork : workPlanList) {
                long carSTime4 = System.currentTimeMillis();
                kfkHandleParam.setWorkPlan(inWork);
                currentCarTrack.setGridId(inWork.getGridId());
                currentCarTrack.setJobType(null == inWork.getType() ? 0 : inWork.getType());
                currentCarTrack.setWorkTypeId(inWork.getWorkTypeId());
                currentCarTrack.setWorkTypeName(inWork.getWorkTypeName());
                Grid grid = gridMap.get(inWork.getGridId());
                if (currentCarTrack.getJobType() == 2 || currentCarTrack.getJobType() == 3) {
                    if (null == grid) {
                        continue;
                    }
                    kfkHandleParam.setGrid(grid);
                    boolean isInGrid = DistanceUtils.insideGrid(Double.parseDouble(currentCarTrack.getLng()), Double.parseDouble(currentCarTrack.getLat()), grid);
                    kfkHandleParam.setIsInGrid(isInGrid);
                }
//                        kfkHandleParam = checkInGrid(kfkHandleParam);
                // 获取班次
                WorkKaoqin workKaoqin = kfkDealService.getKaoqin(kfkHandleParam.getLocationDate(), inWork.getWorkGroupId());
                if (null != workKaoqin) {
                    currentCarTrack.setShiftId(workKaoqin.getWorkKaoqinId());
                    kfkHandleParam.setWorkKaoqin(workKaoqin);
                    if (StringUtils.isNotEmpty(workKaoqin.getSbsj()) && StringUtils.isNotEmpty(workKaoqin.getXbsj())) {
                        currentCarTrack.setShiftStartDate(StringUtils.getAllDate(currentCarTrack.getTimestamp(), workKaoqin.getSbsj()));
                        currentCarTrack.setShiftEndDate(StringUtils.getAllDate(currentCarTrack.getTimestamp(), workKaoqin.getXbsj()));
                    } else {
                        //1:夏季,2:冬季
                        String season = DateUtils.getCurrentSeason(currentCarTrack.getTimestamp());
                        if ("summer".equals(season)) {
                            currentCarTrack.setShiftStartDate(StringUtils.getAllDate(currentCarTrack.getTimestamp(), workKaoqin.getXsbsj()));
                            currentCarTrack.setShiftEndDate(StringUtils.getAllDate(currentCarTrack.getTimestamp(), workKaoqin.getXxbsj()));
                        } else {
                            currentCarTrack.setShiftStartDate(StringUtils.getAllDate(currentCarTrack.getTimestamp(), workKaoqin.getDsbsj()));
                            currentCarTrack.setShiftEndDate(StringUtils.getAllDate(currentCarTrack.getTimestamp(), workKaoqin.getDxbsj()));
                        }
                    }
                    kfkHandleParam.setShiftStartDate(currentCarTrack.getShiftStartDate());
                    kfkHandleParam.setShiftEndDate(currentCarTrack.getShiftEndDate());
                }
                //判断在网格内
                if (kfkHandleParam.getIsInGrid()) {
                    setWorkMileage(currentCarTrack, tlCar, kfkHandleParam);

                } else {
                    //车辆更新离岗
                    tlCar.setOnguardstatus(CommonConstant.ON_GUARD_YES);
                }
                tlCarMapper.updateById(kfkHandleParam.getTlCar());
                //判断是否在工作时间
                setWorkTime(kfkHandleParam, grid, inWork);
                //添加作业规则
                setWorkRuleAndItems(kfkHandleParam, inWork);

                if (0 == abnormalResult.getIsEmergency()) {
                    /**
                     * 违规处理
                     */
                    setViolations(currentCarTrack, kfkHandleParam);
                }
                long carSTime5 = System.currentTimeMillis();

                log.info("=====carLocationHandle3=执行时间(毫秒)：{}", carSTime5 - carSTime4);
//                //打卡
//                employeePunchCardService.punchCard(kfkHandleParam, tlCar);
            }
        } catch (Exception e) {
            log.error("World peace is the greatest prize of all" + e.getMessage(), e);
        } finally {
            String today = DateUtil.formatDate(currentCarTrack.getTimestamp());

            kfkCarLocationMapper.insert(kfkCarLocation);

            currentCarTrack.setAverageFuelConsumption(StringUtils.isNotEmpty(abnormalResult.getValue()) ? abnormalResult.getValue() : BigDecimal.ZERO);
            if (isInsert && !locationUtil.realOffLine(kfkHandleParam.getTwoPointDistanceDiffer(),
                    Long.valueOf(kfkHandleParam.getTwoPointTimeDiffer()))) {
                carTrackMapper.insert(currentCarTrack);
                //该车辆当天最后一条轨迹数据
                RedisUtil.set(CarTrackLastOneKeyToday.token, currentCarTrack.getCarId() + "_" + today, currentCarTrack);
                //该车辆永久最后一条轨迹数据
                RedisUtil.set(CarTrackLastOneKey.token, currentCarTrack.getCarId(), currentCarTrack);
                //保存车辆轨迹到redis，轨迹纠偏功能使用
                RedisUtil.setList(CarTrackNoReviseListKey.token, currentCarTrack.getCarId(), currentCarTrack);
                //保存设备在线状态
                RedisUtil.set(EquipOnlineKey.token, currentCarTrack.getEqpNum(), kfkCarLocation);
                //保存车辆油量异常
                if (StringUtils.isEmpty(currentCarTrack.getOilMass()) || currentCarTrack.getOilMass().equals(new BigDecimal(0))) {
                    RedisUtil.set(OilExceptionTodayKey.token, currentCarTrack.getEqpNum(), currentCarTrack.getEqpNum());
                }
            } else {
                log.debug("kfkHandleParam===================" + kfkHandleParam + "------------------------");
            }
            if (Objects.nonNull(currentCarTrack)) {
                carTrackOriginalService.save(JSONObject.parseObject(JSON.toJSONString(currentCarTrack), CarTrackOriginal.class));
            }
        }
    }

    public KfkCarLocation initKfkCarLocation(KfkHandleParam kfkHandleParam) {
        KfkCarLocation kfkCarLocation = new KfkCarLocation();
        kfkCarLocation.setTimestamp(kfkHandleParam.getKfkTime());
        kfkCarLocation.setEqpnum(kfkHandleParam.getEqpnum());
        kfkCarLocation.setLocation(kfkHandleParam.getLocation());
        kfkCarLocation.setState(kfkHandleParam.getState());
        kfkCarLocation.setOilmass(kfkHandleParam.getOilmass());
        kfkCarLocation.setMileage(kfkHandleParam.getMileage());
        kfkCarLocation.setStatus(kfkHandleParam.getStatus());
        kfkCarLocation.setSpeed(kfkHandleParam.getSpeed());
        kfkCarLocation.setDirection(kfkHandleParam.getDirection());
        kfkCarLocation.setLat(kfkHandleParam.getLat());
        kfkCarLocation.setLon(kfkHandleParam.getLon());
        kfkCarLocation.setDeviceTime(kfkHandleParam.getLocationDate());
        kfkCarLocation.setCreateTime(kfkHandleParam.getCurrentSystemDate());
        return kfkCarLocation;
    }

    public CarTrack initCarTrack(KfkHandleParam kfkHandleParam) {
        CarTrack currentCarTrack = new CarTrack();
        currentCarTrack.setId(kfkHandleParam.getCarTrackId());
        currentCarTrack.setEqpNum(kfkHandleParam.getEqpnum());
        currentCarTrack.setWorkMonth(StringUtils.dateToStr(kfkHandleParam.getLocationDate(), "yyyy-MM"));
        currentCarTrack.setWorkDay(kfkHandleParam.getLocationDate());
        currentCarTrack.setLng(kfkHandleParam.getLon());
        currentCarTrack.setLat(kfkHandleParam.getLat());
        currentCarTrack.setLocation(kfkHandleParam.getLon() + "," + kfkHandleParam.getLat());
        currentCarTrack.setAddress(kfkHandleParam.getCurrentAddress());
        currentCarTrack.setSpeed(kfkHandleParam.getSpeed());
        currentCarTrack.setMessage("");
        currentCarTrack.setIsDanger(0);
        currentCarTrack.setIsWarning(0);
        currentCarTrack.setTimestamp(kfkHandleParam.getLocationDate());
        currentCarTrack.setStatus(Integer.parseInt(kfkHandleParam.getStatus()));
        currentCarTrack.setCreateTime(kfkHandleParam.getCurrentSystemDate());
        currentCarTrack.setDangerOil(0.0);
        currentCarTrack.setDangerOverSpeed(0);
        currentCarTrack.setWarningOverSpeed(0);
        currentCarTrack.setWarningDriveEmpty(0);
        currentCarTrack.setWarningLowSpeed(0);
        currentCarTrack.setWarningStay(0);
        currentCarTrack.setWarningLeave(0);
        currentCarTrack.setWarningOil(0);
        currentCarTrack.setMoveSecond(0);
        currentCarTrack.setMileage(kfkHandleParam.getMileage());
        currentCarTrack.setIsInGrid(0);
        currentCarTrack.setDirection(kfkHandleParam.getDirection());
        return currentCarTrack;
    }

    private KfkHandleParam setKfkHandleParam(Map value) {
        Map content = JSONObject.parseObject(String.valueOf(value.get("content")), Map.class);
        Map contentInfo = JSONObject.parseObject(String.valueOf(content.get("info")), Map.class);
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        /** 获取kafka上传定位基础数据 **/
        String[] locationArray = String.valueOf(contentInfo.get("location")).split(",");
        //上传定位时间
        Date locationDate = null;
        try {
            locationDate = (null == contentInfo.get("dateTime")) ? null : sf.parse(contentInfo.get("dateTime").toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //纬度
        String lat = locationArray[0];
        //经度
        String lon = locationArray[1];
        //车辆编号  86201171128
        String eqpNum = String.valueOf(value.get("no"));
        //坐标经纬度
        String location = String.valueOf(contentInfo.get("location"));
        //在线状态：1 在线 0 不在线
        String state = String.valueOf(value.get("state"));
        //油量百分比(整数部分)
        Double oilMass = StringUtils.isEmpty(String.valueOf(contentInfo.get("oilMass"))) ? 0.0 : Double.parseDouble(String.valueOf(contentInfo.get("oilMass")));
        //油量百分比
        Double oilPercent = oilMass / 100;
        //车辆行驶里程
        Double mileage = StringUtils.isEmpty(String.valueOf(null == contentInfo.get("mileage") ? "" : contentInfo.get("mileage"))) ? 0.0 : Double.parseDouble(String.valueOf(null == contentInfo.get("mileage") ? "" : contentInfo.get("mileage")));
        String status = String.valueOf(contentInfo.get("status"));
        //速度（单位为1/10千米每小时）
        Integer speed = Integer.parseInt(String.valueOf(contentInfo.get("speed"))) / 10;
        //方向
        String direction = String.valueOf(contentInfo.get("direction"));
        //高度
        String altitude = String.valueOf(null == contentInfo.get("altitude") ? "" : contentInfo.get("altitude"));

        // kafka数据保存到对象中
        KfkHandleParam kfkHandleParam = new KfkHandleParam();
        kfkHandleParam.setLocationDate(locationDate);
        kfkHandleParam.setLat(lat);
        kfkHandleParam.setLon(lon);
        kfkHandleParam.setEqpnum(eqpNum);
        kfkHandleParam.setLocation(location);
        kfkHandleParam.setState(state);
        kfkHandleParam.setOilmass(oilMass);
        kfkHandleParam.setOilPercent(oilPercent);
        kfkHandleParam.setMileage(mileage);
        kfkHandleParam.setStatus(status);
        kfkHandleParam.setSpeed(speed);
        kfkHandleParam.setDirection(direction);
        kfkHandleParam.setAltitude(altitude);
        kfkHandleParam.setCurrentSystemDate(new Date());
        /** 保存车辆轨迹 **/
        String currentAddress = locationUtil.getAddress(lon, lat);
        if (StringUtils.isNotEmpty(currentAddress)) {
            kfkHandleParam.setCurrentAddress(currentAddress);
        } else {
            kfkHandleParam.setCurrentAddress("");
        }


        return kfkHandleParam;
    }

    private void setTlCarAndKfakHandle(TlCar tlCar, KfkHandleParam kfkHandleParam) {
        //油箱
        Integer oilBox = getOilVolume(tlCar);
        kfkHandleParam.setTlCar(tlCar);
        kfkHandleParam.setCarId(tlCar.getId());
        kfkHandleParam.setOilBox(oilBox);

        //实时更新车辆的定位坐标、速度、车辆外设开关状态
        tlCar.setAddr(kfkHandleParam.getLon() + "," + kfkHandleParam.getLat());
        tlCar.setCarStatus(kfkHandleParam.getStatus());
        tlCar.setSpeed(kfkHandleParam.getSpeed());
        tlCarMapper.updateById(tlCar);
        TlCarType tlCarType = tlCarTypeService.getFromRedis(tlCar.getCartypeid());
        kfkHandleParam.setTlCarType(tlCarType);
    }

    public List<kfkDealCarWorkPlan> workPlanList(TlCar tlCar, KfkHandleParam kfkHandleParam) {
        /** 查询车辆考勤信息，存入kfkDealCarWorkPlan **/
        Date locationDate = kfkHandleParam.getLocationDate();
        String currentTime = TimeUtil.formatTime2String(locationDate, "yyyy-MM-dd");
        String key = tlCar.getId() + currentTime;
        List<JSONObject> list = RedisUtil.get(CarRptTodayKey.token, key, List.class);

        List<RptCarWork> rptCarWorkList = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            QueryWrapper<RptCarWork> rptCarWorkQueryWrapper = new QueryWrapper<>();
            rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getWorkDate, currentTime);
            rptCarWorkQueryWrapper.lambda().eq(RptCarWork::getCarId, tlCar.getId());
            rptCarWorkList = rptCarWorkMapper.selectList(rptCarWorkQueryWrapper);
            RedisUtil.set(CarRptTodayKey.token, key, rptCarWorkList);
        } else {
            for (JSONObject jsonObject : list) {
                RptCarWork rptCarWork = JSONObject.parseObject(JSONObject.toJSONString(jsonObject), RptCarWork.class);
                rptCarWorkList.add(rptCarWork);
            }
        }
        List<kfkDealCarWorkPlan> kfkDealCarWorkPlanList = rtpCarWorkList(rptCarWorkList);
        return kfkDealCarWorkPlanList;
    }

    public List<kfkDealCarWorkPlan> rtpCarWorkList(List<RptCarWork> rptCarWorkList) {
        List<kfkDealCarWorkPlan> kfkDealCarWorkPlanArrayList = new ArrayList<>();
        rptCarWorkList.forEach(rptCarWork -> {
            kfkDealCarWorkPlan kfkDealCarWorkPlan = new kfkDealCarWorkPlan();
            if (rptCarWork.getWorkType() == 2) {
                kfkDealCarWorkPlan.setId(rptCarWork.getPlanId());
                kfkDealCarWorkPlan.setPlanName(rptCarWork.getPlanName());
                kfkDealCarWorkPlan.setGridId(rptCarWork.getGridId());
                kfkDealCarWorkPlan.setWorkTypeId(rptCarWork.getWorkTypeId());
                kfkDealCarWorkPlan.setWorkTypeName(rptCarWork.getWorkTypeName());
                kfkDealCarWorkPlan.setWorkRuleId(rptCarWork.getRuleId());
                kfkDealCarWorkPlan.setWorkGroupId(rptCarWork.getGroupId());
                kfkDealCarWorkPlan.setFrequency(rptCarWork.getTangCi());
                kfkDealCarWorkPlan.setType(2);
            } else if (rptCarWork.getWorkType() == 3) {
                kfkDealCarWorkPlan.setId(rptCarWork.getPlanId());
                kfkDealCarWorkPlan.setPlanName(rptCarWork.getPlanName());
                kfkDealCarWorkPlan.setGridId(rptCarWork.getGridId());
                kfkDealCarWorkPlan.setWorkRuleId(rptCarWork.getRuleId());
                kfkDealCarWorkPlan.setWorkGroupId(rptCarWork.getGroupId());
                kfkDealCarWorkPlan.setFrequency(1);
                kfkDealCarWorkPlan.setType(3);
            } else if (rptCarWork.getWorkType() == 4) {
                kfkDealCarWorkPlan.setId(rptCarWork.getPlanId());
                kfkDealCarWorkPlan.setPlanName(rptCarWork.getPlanName());
                kfkDealCarWorkPlan.setGridId(rptCarWork.getGridId());
                kfkDealCarWorkPlan.setWorkRuleId(rptCarWork.getRuleId());
                kfkDealCarWorkPlan.setWorkGroupId(rptCarWork.getGroupId());
                kfkDealCarWorkPlan.setFrequency(1);
                kfkDealCarWorkPlan.setType(4);
            }
            kfkDealCarWorkPlanArrayList.add(kfkDealCarWorkPlan);
        });
        return kfkDealCarWorkPlanArrayList;
    }

    private AbnormalResult setKfkHandleAndCarTrack(KfkHandleParam kfkHandleParam, CarTrack preCarTrack, CarTrack currentCarTrack) throws ParseException {

        //停留状态
        boolean ifStay = locationUtil.checkTwoPointSame(kfkHandleParam.getLon(), kfkHandleParam.getLat(), kfkHandleParam.getPreCarTrack().getLng(), kfkHandleParam.getPreCarTrack().getLat());
        kfkHandleParam.setIfStay(ifStay);
        if (!ifStay) {
            kfkHandleParam.getTlCar().setMove("0");
            currentCarTrack.setMoveSecond(preCarTrack.getMoveSecond() + kfkHandleParam.getTwoPointTimeDiffer());
        } else {
            kfkHandleParam.getTlCar().setMove("1");
            currentCarTrack.setWarningStay(preCarTrack.getWarningStay() + kfkHandleParam.getTwoPointTimeDiffer());
        }
        //计算加油
        BigDecimal nowOilNum = new BigDecimal(kfkHandleParam.getOilmass()).multiply(new BigDecimal(kfkHandleParam.getOilBox())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
        List<CarTrack> carTrackListForAddOilHandle = getCarTrackList(kfkHandleParam.getPreCarTrack().getCarId(), kfkHandleParam.getLocationDate());
        Double num = calculateAddOilNum(carTrackListForAddOilHandle, kfkHandleParam.getLocationDate(), 5, nowOilNum, kfkHandleParam.getPreCarTrack().getCarId(), kfkHandleParam.getOilBox());
        //计算加油比
        currentCarTrack.setAddOilNum(num);
        currentCarTrack.setAddOilProp(new BigDecimal(num).divide(new BigDecimal(kfkHandleParam.getOilBox()), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());

        //是否应急
        boolean isEmergency = isEmergency(kfkHandleParam.getTlCar().getCarnumber(), "car", kfkHandleParam.getLocationDate());

        AbnormalResult abnormalResult = new AbnormalResult();

        if (isEmergency) {
            abnormalResult.setIsEmergency(1);
            currentCarTrack.setIsEmergency(1);
        } else {
            /**
             * 车辆报警处理
             */
            PerformanceMonitor.begin("-----------------------车辆报警处理------------------~");
            abnormalResult = carAlarmHandle(kfkHandleParam);
            PerformanceMonitor.end();

            abnormalResult.setIsEmergency(0);
            currentCarTrack.setIsEmergency(0);

            if (1 == abnormalResult.getIsOilmassAbnormal()) {
                currentCarTrack.setIsOilmassAbnormal(1);
            } else if (1 == abnormalResult.getIsSpeeding()) {
                currentCarTrack.setIsSpeeding(1);
            }
        }
        return abnormalResult;
    }

    public CarTrack setPreCarTrack(
            TlCar tlCar, CarTrack currentCarTrack) {

        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        carTrackQueryWrapper.orderByDesc("timestamp");
        carTrackQueryWrapper.eq("car_id", tlCar.getId());
        carTrackQueryWrapper.last("limit 1");
        CarTrack preCarTrack = carTrackMapper.selectOne(carTrackQueryWrapper);

        //如果没有上次定位则代表是刚开始执行
        if (preCarTrack == null) {
            //图简单，懒得判断上次有没有数据了，理论上结果是一样的，取默认值的话，相当于上次数据为正常
            preCarTrack = currentCarTrack;
        }
        return preCarTrack;
    }

    public void setWorkMileage(CarTrack currentCarTrack, TlCar tlCar, KfkHandleParam kfkHandleParam) {
        currentCarTrack.setIsInGrid(1);
        //车辆更新在岗
        tlCar.setOnguardstatus(0);
        tlCar.setAttendance(0);
//        if (null != currentCarTrack.getShiftId()) {
//            QueryWrapper<RptCarWork> carWorkQueryWrapper = new QueryWrapper<>();
//            carWorkQueryWrapper.eq("car_id", currentCarTrack.getCarId());
//            carWorkQueryWrapper.eq("grid_id", currentCarTrack.getGridId());
//            carWorkQueryWrapper.eq("work_date", StringUtils.dateToStr(kfkHandleParam.getCurrentSystemDate(), "yyyy-MM-dd"));
//            carWorkQueryWrapper.eq("shift_id", currentCarTrack.getShiftId());
//            List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(carWorkQueryWrapper);
//            Integer nowProgress;
//            BigDecimal mileage;
//            BigDecimal timeConsuming;
//            BigDecimal oilConsumption;
//            for (RptCarWork rptCarWork : rptCarWorkList) {
//                if (rptCarWork.getWorkType() == 2) {
//                    //在时间内
//                    if (rptCarWork.getPlanStartTime().compareTo(currentCarTrack.getTimestamp()) <= 0 && rptCarWork.getPlanEndTime().compareTo(currentCarTrack.getTimestamp()) >= 0) {
//                        //开启喷头总进度   1  //喷头开启 暂时去掉   && currentCarTrack.getStatus() == 1
//                        nowProgress = rptCarWork.getNowProgress() + currentCarTrack.getDistanceBetween();
////                        if (currentCarTrack.getTimestamp().compareTo(rptCarWork.getPlanEndTime()) <= 0
////                                && currentCarTrack.getTimestamp().compareTo(rptCarWork.getPlanStartTime()) >= 0) {
//                        rptCarWork.setNowProgress(nowProgress);
//
//                        mileage = (null == rptCarWork.getMileage() ? BigDecimal.ZERO : rptCarWork.getMileage()).add(new BigDecimal(currentCarTrack.getDistanceBetween()));
//                        rptCarWork.setMileage(mileage);
//                        //作业耗时
////                        timeConsuming = (null == rptCarWork.getTimeConsuming() ? BigDecimal.ZERO : rptCarWork.getTimeConsuming())
////                                .add(new BigDecimal((currentCarTrack.getTimestamp().getTime() - kfkHandleParam.getPreCarTrack().getTimestamp().getTime()) / 1000));
////                        rptCarWork.setTimeConsuming(timeConsuming);
//                        //作业油耗
//                        BigDecimal addOilNum = null == currentCarTrack.getAddOilNum() ? BigDecimal.ZERO : new BigDecimal(currentCarTrack.getAddOilNum());
//
//                        BigDecimal oilWear = MathUtils.getBigDecimal(kfkHandleParam.getPreCarTrack().getOilMass())
//                                .subtract(MathUtils.getBigDecimal(currentCarTrack.getOilMass()))
//                                .add(addOilNum).setScale(2, BigDecimal.ROUND_HALF_UP);
//
//                        oilConsumption = (null == rptCarWork.getOilConsumption() ? BigDecimal.ZERO : rptCarWork.getOilConsumption()).add(oilWear);
//                        if (oilConsumption.compareTo(BigDecimal.ZERO) < 0) {
//                            oilConsumption = BigDecimal.ZERO;
//                        }
//                        rptCarWork.setOilConsumption(oilConsumption);
//
//                        if (null == rptCarWork.getWorkStartTime() || "".equals(rptCarWork.getWorkStartTime())) {
//                            rptCarWork.setWorkStartTime(currentCarTrack.getTimestamp());
//                        }
//                        rptCarWork.setWorkEndTime(currentCarTrack.getTimestamp());
//                        rptCarWorkMapper.updateById(rptCarWork);
//                    }
////                    }
//                } else {
//                    if (rptCarWork.getPlanStartTime().compareTo(currentCarTrack.getTimestamp()) <= 0 && rptCarWork.getPlanEndTime().compareTo(currentCarTrack.getTimestamp()) >= 0) {
//                        //作业耗时
////                        timeConsuming = (null == rptCarWork.getTimeConsuming() ? BigDecimal.ZERO : rptCarWork.getTimeConsuming()).add(new BigDecimal((currentCarTrack.getTimestamp().getTime() - kfkHandleParam.getPreCarTrack().getTimestamp().getTime()) / 1000));
////                        rptCarWork.setTimeConsuming(timeConsuming);
//                        //作业油耗
//                        BigDecimal oilWear = MathUtils.getBigDecimal(kfkHandleParam.getPreCarTrack().getOilMass()).subtract(MathUtils.getBigDecimal(currentCarTrack.getOilMass())).add(new BigDecimal(currentCarTrack.getAddOilNum())).setScale(2, BigDecimal.ROUND_HALF_UP);
//                        oilConsumption = (null == rptCarWork.getOilConsumption() ? BigDecimal.ZERO : rptCarWork.getOilConsumption()).add(oilWear);
//                        rptCarWork.setOilConsumption(oilConsumption);
//
//                        mileage = (null == rptCarWork.getMileage() ? BigDecimal.ZERO : rptCarWork.getMileage()).add(new BigDecimal(currentCarTrack.getDistanceBetween()));
//                        rptCarWork.setMileage(mileage);
//
//                        if (null == rptCarWork.getWorkStartTime() || "".equals(rptCarWork.getWorkStartTime())) {
//                            rptCarWork.setWorkStartTime(currentCarTrack.getTimestamp());
//                        }
//                        rptCarWork.setWorkEndTime(currentCarTrack.getTimestamp());
//                        rptCarWorkMapper.updateById(rptCarWork);
//                    }
//                }
//            }
//        }

//        QueryWrapper<RptCarWork> carWorkQueryWrapper = new QueryWrapper<>();
//        carWorkQueryWrapper.lambda().eq(RptCarWork::getWorkDate, StringUtils.dateToStr(new Date(), "yyyy-MM-dd"));
//        carWorkQueryWrapper.lambda().eq(RptCarWork::getWorkType, 3);
//        carWorkQueryWrapper.lambda().eq(RptCarWork::getCarId, currentCarTrack.getCarId());
//        List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(carWorkQueryWrapper);
//        CarTrack finalCurrentCarTrack = currentCarTrack;
//
//        QueryWrapper<CarPlanCollectPoint> carPlanCollectPointQueryWrapper = new QueryWrapper<>();
//        List<CarPlanCollectPoint> carPlanCollectPointList = carPlanCollectPointMapper.selectList(carPlanCollectPointQueryWrapper);
//        Map<String, List<CarPlanCollectPoint>> carPlanCollectPointMap = carPlanCollectPointList.stream().collect(Collectors.groupingBy(CarPlanCollectPoint::getCarPlanId));
//
//        List<String> carPlanCollectPointId = new ArrayList<>();
//        rptCarWorkList.forEach(rptCarWork -> {
//            CarPlan carPlan = carPlanMapper.selectById(rptCarWork.getPlanId());
//            if (null != carPlan) {
//                List<CarPlanCollectPoint> carPlanCollectPointList1 = carPlanCollectPointMap.get(carPlan.getId());
//                if (null != carPlanCollectPointList1) {
//                    for (CarPlanCollectPoint carPlanCollectPoint : carPlanCollectPointList1) {
//                        carPlanCollectPointId.add(carPlanCollectPoint.getCollectPointId());
//                    }
//                }
//            }
//            if (!carPlanCollectPointId.isEmpty()) {
//                QueryWrapper<TlFacilities> tlFacilitiesQueryWrapper = new QueryWrapper<>();
//                tlFacilitiesQueryWrapper.lambda().in(TlFacilities::getId, carPlanCollectPointId);
//                List<TlFacilities> tlFacilitiesList = tlFacilitiesMapper.selectList(tlFacilitiesQueryWrapper);
//                StringBuffer inFacIds = new StringBuffer();
//                for (TlFacilities tlFacilities : tlFacilitiesList) {
//                    String[] faclAddr = tlFacilities.getFacladdr().split(",");
//                    String lngAddr = faclAddr[0];
//                    String latAddr = faclAddr[1];
//                    Boolean flag = DistanceUtils.insideCircle(Double.parseDouble(finalCurrentCarTrack.getLng()), Double.parseDouble(finalCurrentCarTrack.getLat()), Double.parseDouble(lngAddr), Double.parseDouble(latAddr), Double.parseDouble(tlFacilities.getRadii().toString()));
//                    if (flag) {
//                        inFacIds.append(tlFacilities.getId() + ",");
//                    }
//                }
//                String saveIds = inFacIds.toString();
//                if (!StringUtils.isEmpty(saveIds)) {
//                    if (null != rptCarWork.getStatus() && rptCarWork.getStatus() != 2) {
//                        finalCurrentCarTrack.setFacilityId(saveIds.substring(0, saveIds.length() - 1));
//                        finalCurrentCarTrack.setCleanType(0);
//                    }
//                }
//            }
//        });
    }

    public void setWorkTime(KfkHandleParam kfkHandleParam, Grid grid, kfkDealCarWorkPlan inWork) {
        //判断是否在工作时间
        if (null != grid) {
            QueryWrapper<RptCarWork> carWorkQueryWrapper = new QueryWrapper<>();
            carWorkQueryWrapper.eq("car_id", kfkHandleParam.getCarId());
            carWorkQueryWrapper.eq("plan_id", inWork.getId());
            carWorkQueryWrapper.eq("work_date", StringUtils.dateToStr(kfkHandleParam.getLocationDate(), "yyyy-MM-dd"));
            carWorkQueryWrapper.eq("grid_id", grid.getGridId());
            carWorkQueryWrapper.eq("group_id", inWork.getWorkGroupId());
            List<RptCarWork> rptCarWorkList = rptCarWorkMapper.selectList(carWorkQueryWrapper);
            if (!CollectionUtils.isEmpty(rptCarWorkList)) {
                for (RptCarWork rptCarWork : rptCarWorkList) {
                    if (rptCarWork.getPlanStartTime().compareTo(kfkHandleParam.getLocationDate()) < 0 && rptCarWork.getPlanEndTime().compareTo(kfkHandleParam.getLocationDate()) > 0) {
                        kfkHandleParam.setIsInWorktime(true);
                    }
                }
            }
        }
    }

    public void setWorkRuleAndItems(KfkHandleParam kfkHandleParam, kfkDealCarWorkPlan inWork) {
        QueryWrapper<WorkRule> workRuleQueryWrapper = new QueryWrapper<>();
        workRuleQueryWrapper.eq("work_rule_id", inWork.getWorkRuleId());
        workRuleQueryWrapper.eq("is_enable", CommonConstant.ZY_ENABLE_YES);
        WorkRule workRule = workRuleMapper.selectOne(workRuleQueryWrapper);
        kfkHandleParam.setWorkRule(workRule);
        if (null == workRule) {
            log.error("未找到作业规则，work_rule_id:{}", inWork.getWorkRuleId());
        }

        QueryWrapper<WorkRuleItem> workRuleItemQueryWrapper = new QueryWrapper<>();
        workRuleItemQueryWrapper.eq("rule_id", inWork.getWorkRuleId());
        workRuleItemQueryWrapper.eq("is_enable", CommonConstant.ZY_ENABLE_YES);
        List<WorkRuleItem> workRuleItemList = workRuleItemMapper.selectList(workRuleItemQueryWrapper);
        kfkHandleParam.setWorkRuleItems(workRuleItemList);
        if (CollectionUtils.isEmpty(workRuleItemList)) {
            log.error("未找到作业规则项，rule_id:{}", inWork.getWorkRuleId());
        }
    }

    public void setViolations(CarTrack currentCarTrack, KfkHandleParam kfkHandleParam) {
        //违规处理
        if (kfkHandleParam.getIsInWorktime()
                && null != kfkHandleParam.getWorkRule()
                && "1".equals(kfkHandleParam.getWorkRule().getIsEnable())
                && !CollectionUtils.isEmpty(kfkHandleParam.getWorkRuleItems())
                && Objects.nonNull(kfkHandleParam.getWorkKaoqin())
        ) {
            /**
             * 车辆违规处理
             */
            PerformanceMonitor.begin("-----------------------车辆违规处理------------------~");
            AbnormalResult abnormalResult = carViolationHandle(kfkHandleParam);
            PerformanceMonitor.end();

            if (1 == abnormalResult.getIsStop()) {
                currentCarTrack.setIsStop(1);
            }
            if (1 == abnormalResult.getIsSpeedLimit()) {
                currentCarTrack.setIsSpeedLimit(1);
            }
            if (1 == abnormalResult.getIsEmptyTravel()) {
                currentCarTrack.setIsEmptyTravel(1);
            }
        }
    }

    private AbnormalResult carAlarmHandle(KfkHandleParam kfkHandleParam) throws ParseException {
        AbnormalResult abnormalResult = new AbnormalResult();
        String today = DateUtil.formatDate(kfkHandleParam.getLocationDate());
        List<TlThreshold> tlThresholdList = tlThresholdService.getCarThresholdsFromRedis(kfkHandleParam.getCarId());
        for (TlThreshold tlThreshold : tlThresholdList) {
            //两点相差时间秒数
            Integer twoPointTimeDiffer = Objects.nonNull(kfkHandleParam.getTwoPointTimeDiffer()) ? kfkHandleParam.getTwoPointTimeDiffer() : 0;
            String sysname = tlThreshold.getSysname();
            switch (sysname) {
                case "超速":
                    PerformanceMonitor.begin("-----------------------车辆报警超速整块执行时间------------------~");
                    if ("0".equals(tlThreshold.getStatus())) {
                        break;
                    }
                    JSONObject speedThresholdDetail = JSONObject.parseObject(tlThreshold.getThreshold());
                    if (kfkHandleParam.getSpeed() >= Double.parseDouble(speedThresholdDetail.get("xs").toString())) {
                        //某时间段最大速
                        int maxSpeed = Objects.nonNull(RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) : 0;
                        if (kfkHandleParam.getSpeed() > maxSpeed) {
                            RedisUtil.set(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, kfkHandleParam.getSpeed());
                        }

                        int carAlarmSpeedKeepTime = Objects.nonNull(RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                        RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carAlarmSpeedKeepTime);

                        //保存车辆报警表
                        abnormalResult = saveAlarmCar(kfkHandleParam, tlThreshold, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * twoPointTimeDiffer));
                        abnormalResult.setIsSpeeding(1);

                        kfkHandleParam.getCurrentCarTrack().setIsDanger(1);
                        kfkHandleParam.getCurrentCarTrack().setDangerOverSpeed(kfkHandleParam.getPreCarTrack().getDangerOverSpeed() + kfkHandleParam.getTwoPointTimeDiffer());
                        kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());
                        kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("dangerOverSpeed");
                        kfkHandleParam.getCurrentCarTrack().setIsSpeeding(1);

                        if (2 == abnormalResult.getIskeep()) {
                            // 发送报警信息到前台
                            sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_ALARM, sysname, "超速");
                        }
                    } else if (kfkHandleParam.getSpeed() >= Double.parseDouble(speedThresholdDetail.get("m_xs").toString())) {
                        //速度持续时间(分钟)
                        JSONObject threshold1 = JSONObject.parseObject(tlThreshold.getThreshold());
                        int duration = 60 * Integer.parseInt(threshold1.get("m_sj").toString());

                        //超速模式一达到阈值持续保持时间
                        int carAlarmSpeedKeepTime = Objects.nonNull(RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmSpeedKeepTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                        RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carAlarmSpeedKeepTime);

                        //超过阈值
                        if (carAlarmSpeedKeepTime >= duration * 60) {
                            //某时间段最大速
                            int maxSpeed = Objects.nonNull(RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) : 0;
                            if (kfkHandleParam.getSpeed() > maxSpeed) {
                                RedisUtil.set(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, kfkHandleParam.getSpeed());
                            }

                            String starttime = StringUtils.FormatData(new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * duration * 60));
                            //保存车辆报警表
                            abnormalResult = saveAlarmCar(kfkHandleParam, tlThreshold, StringUtils.StringToDate(starttime));

                            kfkHandleParam.getCurrentCarTrack().setIsDanger(1);
                            kfkHandleParam.getCurrentCarTrack().setDangerOverSpeed(kfkHandleParam.getPreCarTrack().getDangerOverSpeed() + kfkHandleParam.getTwoPointTimeDiffer());
                            kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());
                            kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("dangerOverSpeed");
                            kfkHandleParam.getCurrentCarTrack().setIsSpeeding(1);

                            abnormalResult.setIsSpeeding(1);

                            if (2 == abnormalResult.getIskeep()) {
                                // 发送报警信息到前台
                                sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_ALARM, sysname, "超速");
                            }
                        }
                    } else {
                        //超速持续保持时间
                        RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                        //某时间段最大速
                        RedisUtil.set(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                    }
                    PerformanceMonitor.end();
                    break;
                case "疲劳驾驶":
                    break;
                case "离线":
                    break;
                case "出区域":
                    break;
                case "漏油":
                    PerformanceMonitor.begin("-----------------------车辆报警漏油执行时间------------------~");
                    if ("0".equals(tlThreshold.getStatus())) {
                        abnormalResult.setValue(BigDecimal.ZERO);
                        break;
                    }
                    // 油量为0时不处理
                    if (kfkHandleParam.getCurrentCarTrack().getOilMass().compareTo(BigDecimal.ZERO) <= 0) {
                        abnormalResult.setValue(BigDecimal.ZERO);
                        break;
                    }

                    //检测时间间隔
                    int timeinterval;//单位分钟
                    //阀值油耗差
//                    BigDecimal yhc;
                    //阀值油耗限额
                    BigDecimal yhxe;
                    timeinterval = tlThreshold.getTimeinterval();
                    JSONObject threshold1 = JSONObject.parseObject(tlThreshold.getThreshold());
//                    yhc = new BigDecimal(threshold1.get("yxrcl").toString());
                    yhxe = new BigDecimal(threshold1.get("yhxe").toString());
                    Map consumptionPer = getConsumptionPer(kfkHandleParam.getCarId(), StringUtils.DateFormat(new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * 60 * timeinterval)), StringUtils.DateFormat(kfkHandleParam.getLocationDate()));
                    //获取检测时间间隔的总耗油
                    BigDecimal oilMassSum = new BigDecimal(String.valueOf(consumptionPer.get("oilMassSum")));

                    //获取检测时间间隔的百公里油耗
                    BigDecimal timeintervalConsumptionPer = new BigDecimal(String.valueOf(consumptionPer.get("consumptionPer")));
                    timeintervalConsumptionPer = timeintervalConsumptionPer.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
                    abnormalResult.setValue(timeintervalConsumptionPer);

                    if (oilMassSum.compareTo(yhxe) > 0) {

                        int carAlarmSpeedKeepTime = Objects.nonNull(RedisUtil.get(CarAlarmOilTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmOilTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + 1000 * 60 * timeinterval : 1000 * 60 * timeinterval;
                        RedisUtil.set(CarAlarmOilTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carAlarmSpeedKeepTime);

                        //保存车辆报警表
                        abnormalResult = saveAlarmCar(kfkHandleParam, tlThreshold, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * 60 * timeinterval));

                        // 报警：查询上次定位时油量，下降10%为漏油
                        Double danger_oil = 0d;
                        if (0 != kfkHandleParam.getOilBox()) {
                            danger_oil = (oilMassSum.doubleValue() / kfkHandleParam.getOilBox()) * 100;
                        }
                        danger_oil = Double.parseDouble(NumberUtil.decimalFormat("00.00", danger_oil));
                        kfkHandleParam.getCurrentCarTrack().setIsDanger(1);
                        kfkHandleParam.getCurrentCarTrack().setDangerOil(danger_oil);
                        kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());
                        kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("dangerOil");
                        kfkHandleParam.getCurrentCarTrack().setIsOilmassAbnormal(1);

                        abnormalResult.setIsOilmassAbnormal(1);

                        //判断是否最新漏油
                        if (2 == abnormalResult.getIskeep()) {
                            // 发送报警信息到前台
                            sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_ALARM, sysname, "漏油");
                        }

                    } else {
//                        //漏油持续时间
                        RedisUtil.set(CarAlarmOilTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                        //最大百公里油耗
                        RedisUtil.set(CarAlarmAvgOilConsumptionKeyToday.token, kfkHandleParam.getCarId() + "_" + today, "0");
                    }
                    PerformanceMonitor.end();
                    break;
                case "电源欠压":

                    break;
                case "电源掉电":

                    break;
                case "驾驶超时":
                    break;
                case "定位失败":

                    break;
                case "进区域":
                    break;
                default:
                    break;
            }

        }
        return abnormalResult;
    }

    public Map DTULocationHandle(Map map) {
        Map result = new HashMap();
        try {
            Map content = JSONObject.parseObject(String.valueOf(map.get("content")), Map.class);
            Map info = JSONObject.parseObject(String.valueOf(content.get("info")), Map.class);
            //上传时间
            String datestr = map.get("locationDate").toString();//Date的默认格式显示
            Date date = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK).parse(datestr);
            //格式化
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String sDate = sdf.format(date);
            Date locationDate = StringUtils.StringToDate(sDate);

            QueryWrapper<TlEquip> tlEquipQueryWrapper = new QueryWrapper<>();
            tlEquipQueryWrapper.eq("equipcode", String.valueOf(map.get("no")));
            tlEquipQueryWrapper.last("limit 1");
            TlEquip equip = equipMapper.selectOne(tlEquipQueryWrapper);
            if (null == equip) {
                return result;
            }
            TlFacilities facilities = facilitiesMapper.selectById(equip.getBindobjid());
            if (null == facilities) {
                return result;
            }
            String bjName;
            String name;
            if (info.containsKey("category") && info.get("category").equals("smoke")) {
                bjName = "烟雾报警";
                name = "ywnd";
            } else if (info.containsKey("category") && info.get("category").equals("humidity")) {
                bjName = "硫化氢报警";
                name = "lhqnd";
            } else if (info.containsKey("category") && info.get("category").equals("ammonia")) {
                bjName = "氨气报警";
                name = "aqnd";
            } else {
                return result;
            }
            TlThreshold threshold = tlThresholdService.getCarOneThresholdFromRedis(facilities.getId(), bjName);
            if (null == threshold) {
                return result;
            }
            if (StringUtils.isNotEmpty(threshold.getStatus()) && "0".equals(threshold.getStatus())) {
                return result;
            }
            JSONObject jsonObject = JSONObject.parseObject(threshold.getThreshold());
            BigDecimal num = new BigDecimal(String.valueOf(jsonObject.get(name)));
            String valueResult = String.valueOf(info.get("value"));
            if (StringUtils.isNotEmpty(valueResult) && valueResult.length() > 3) {
                valueResult = valueResult.replace(valueResult.substring(valueResult.length() - 3), "");
            } else {
                valueResult = "0";
            }
            BigDecimal value = new BigDecimal(valueResult);
            if (Objects.nonNull(num) && num.compareTo(value) <= 0) {
                if ("烟雾报警".equals(bjName)) {
                    if ("0".equals(threshold.getStatus())) {
                        return result;
                    }
                    result.put("is_smoke_alarm", 1);
                } else if ("硫化氢报警".equals(bjName)) {
                    if ("0".equals(threshold.getStatus())) {
                        return result;
                    }
                    result.put("is_hydrogen_sulfide_alarm", 1);
                } else if ("氨气报警".equals(bjName)) {
                    if ("0".equals(threshold.getStatus())) {
                        return result;
                    }
                    result.put("is_ammonia_alarm", 1);
                }
                AbnormalResult abnormalResult = saveAlarmSheshi(equip, facilities, threshold, locationDate, locationDate, value, String.valueOf(info.get("category")));
                if (2 == abnormalResult.getIskeep()) {
                    sendAlarm(equip, facilities, threshold, abnormalResult.getId(), CommonConstant.PUSH_TYPE_ALARM, bjName, bjName);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }

    public Map manholeCoverLocationHandle(KfkManholeCover kfkManholeCover) {

        Map result = new HashMap();
        try {
            QueryWrapper<TlEquip> tlEquipQueryWrapper = new QueryWrapper<>();
            tlEquipQueryWrapper.eq("equipcode", kfkManholeCover.getEqpnum());
            tlEquipQueryWrapper.last("limit 1");
            TlEquip equip = equipMapper.selectOne(tlEquipQueryWrapper);
            if (null == equip) {
                return result;
            }
            TlFacilities facilities = facilitiesMapper.selectById(equip.getBindobjid());
            if (null == facilities) {
                return result;
            }
            List<TlThreshold> thresholds = tlThresholdService.getCarThresholdsFromRedis(facilities.getId());
            if (Objects.nonNull(thresholds) && thresholds.size() > 0) {
                for (TlThreshold threshold :
                        thresholds) {
                    if (StringUtils.isNotEmpty(threshold.getStatus()) && "0".equals(threshold.getStatus())) {
                        return result;
                    }
                    JSONObject jsonObject = JSONObject.parseObject(threshold.getThreshold());
                    BigDecimal ms = new BigDecimal(String.valueOf(jsonObject.get("ms")));

                    switch (threshold.getSysname()) {
                        case "开盖报警":
                            // 更新原有报警时长
                            if (CommonConstant.IS_COVER_ABNORMAL_NO == kfkManholeCover.getIsCoverAbnormal()) {
                                QueryWrapper<AlarmSheshi> queryWrapper = new QueryWrapper<>();
                                queryWrapper.lambda().eq(AlarmSheshi::getSheshiId, facilities.getId());
                                queryWrapper.lambda().eq(AlarmSheshi::getAlarmTypeName, threshold.getSysname());
                                queryWrapper.lambda().last(" ORDER BY alarm_time DESC LIMIT 1");
                                AlarmSheshi alarmSheshi = alarmSheshiMapper.selectOne(queryWrapper);
                                if (Objects.nonNull(alarmSheshi) && alarmSheshi.getAlarmStartTime().compareTo(alarmSheshi.getAlarmEndTime()) == 0) {
                                    updateFacilities(alarmSheshi, kfkManholeCover.getTime(), BigDecimal.ZERO);
                                }
                            }
                            //新增报警
                            if (CommonConstant.IS_COVER_ABNORMAL_YES == kfkManholeCover.getIsCoverAbnormal()) {
                                AbnormalResult abnormalResult = insertFacilities(facilities, threshold, kfkManholeCover.getTime(), kfkManholeCover.getTime(), BigDecimal.ZERO, "");
                                sendAlarm(equip, facilities, threshold, abnormalResult.getId(), CommonConstant.PUSH_TYPE_ALARM, threshold.getSysname(), threshold.getSysname());
                            }
                            break;
                        case "水位超限":
                            // 更新原有报警时长
                            if (CommonConstant.IS_WATER_ABNORMAL_NO == kfkManholeCover.getIsWaterAbnormal()) {
                                QueryWrapper<AlarmSheshi> queryWrapper = new QueryWrapper<>();
                                queryWrapper.lambda().eq(AlarmSheshi::getSheshiId, facilities.getId());
                                queryWrapper.lambda().eq(AlarmSheshi::getAlarmTypeName, threshold.getSysname());
                                queryWrapper.lambda().last(" ORDER BY alarm_time DESC LIMIT 1");
                                AlarmSheshi alarmSheshi = alarmSheshiMapper.selectOne(queryWrapper);
                                if (Objects.nonNull(alarmSheshi) && alarmSheshi.getAlarmStartTime().compareTo(alarmSheshi.getAlarmEndTime()) == 0) {
                                    updateFacilities(alarmSheshi, kfkManholeCover.getTime(), BigDecimal.ZERO);
                                }
                            }
                            //新增报警
                            if (CommonConstant.IS_WATER_ABNORMAL_YES == kfkManholeCover.getIsWaterAbnormal()) {
                                AbnormalResult abnormalResult = insertFacilities(facilities, threshold, kfkManholeCover.getTime(), kfkManholeCover.getTime(), BigDecimal.ZERO, "");
                                sendAlarm(equip, facilities, threshold, abnormalResult.getId(), CommonConstant.PUSH_TYPE_ALARM, threshold.getSysname(), threshold.getSysname());
                            }
                            break;
                    }
                }
            } else {
                return result;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }


    public Double calculateAddOilNum(List<CarTrack> carTrackList, Date time, Integer flag, BigDecimal nowOilNum, String carId, Integer oilBox) {
        log.info("World peace is the greatest prize of all 539  进入方法 flag=" + flag + ",nowOilNum=" + nowOilNum + ",carId=" + carId + ",oilBox=" + oilBox);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(carTrackList) || nowOilNum.compareTo(BigDecimal.ZERO) <= 0
                || (time.getTime() == carTrackList.get(0).getTimestamp().getTime())) {
            return 0.0;
        }
        if (Objects.isNull(time)) {
            time = new Date();
        }
        if (CollectionUtils.isEmpty(carTrackList)) {
            return 0.0;
        }
        if (carTrackList.get(0).getAddOilNum() != null && carTrackList.get(0).getAddOilNum() > 0) {
            if (nowOilNum.subtract(carTrackList.get(0).getOilMass()).compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal value = nowOilNum.
                        subtract(carTrackList.get(0).getOilMass()).
                        setScale(2, BigDecimal.ROUND_HALF_UP);
                log.info("World peace is the greatest prize of all 557  继续加油 flag=" + flag + ",nowOilNum=" + nowOilNum + ",carId=" + carId + ",oilBox=" + oilBox);
                return value.doubleValue();
            }
        } else {
            BigDecimal sum = nowOilNum.subtract(carTrackList.get(0).getOilMass());
            for (int i = 0; i < carTrackList.size() - 1; i++) {
                if (carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO) <= 0 || nowOilNum.compareTo(BigDecimal.ZERO) <= 0 || carTrackList.get(i + 1).getOilMass().compareTo(BigDecimal.ZERO) <= 0) {
                    continue;
                }
                BigDecimal o = carTrackList.get(i).getOilMass().subtract(carTrackList.get(i + 1).getOilMass());
                if (o.compareTo(BigDecimal.ZERO) >= 0) {
                    sum = sum.add(o);
                } else {
                    break;
                }
                if (sum.compareTo(new BigDecimal(String.valueOf(flag))) >= 0) {
                    break;
                }
            }
            if (sum.compareTo(new BigDecimal(String.valueOf(flag))) >= 0) {
                for (int i = 0; i < carTrackList.size() - 1; i++) {
                    if (carTrackList.get(i).getOilMass().compareTo(BigDecimal.ZERO) <= 0 || nowOilNum.compareTo(BigDecimal.ZERO) <= 0 || carTrackList.get(i + 1).getOilMass().compareTo(BigDecimal.ZERO) <= 0) {
                        continue;
                    }
                    BigDecimal o = carTrackList.get(i).getOilMass().subtract(carTrackList.get(i + 1).getOilMass());
                    if (o.compareTo(BigDecimal.ZERO) >= 0) {
                        BigDecimal val = carTrackList.get(i).getOilMass().
                                subtract(carTrackList.get(i + 1).getOilMass()).
                                setScale(2, BigDecimal.ROUND_HALF_UP);
                        carTrackList.get(i).setAddOilNum(val.doubleValue());
                        carTrackList.get(i).setAddOilProp(val.divide(new BigDecimal(oilBox), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
                    } else {
                        break;
                    }
                }
                carTrackService.updateBatchById(carTrackList);
                if (null != carTrackList.get(0).getOilMass() && nowOilNum.subtract(carTrackList.get(0).getOilMass()).compareTo(BigDecimal.ZERO) > 0) {
                    log.info("World peace is the greatest prize of all 594  开始加油 flag=" + flag + ",nowOilNum=" + nowOilNum + ",carId=" + carId + ",oilBox=" + oilBox);
                    return nowOilNum.
                            subtract(carTrackList.get(0).getOilMass()).
                            setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                } else {
                    log.info("World peace is the greatest prize of all 599  加油为零 flag=" + flag + ",nowOilNum=" + nowOilNum + ",carId=" + carId + ",oilBox=" + oilBox);
                    return 0.0;
                }
            }
        }
        log.info("World peace is the greatest prize of all 605  加油为零 flag=" + flag + ",nowOilNum=" + nowOilNum + ",carId=" + carId + ",oilBox=" + oilBox);
        return 0.0;
    }

    private List<CarTrack> getCarTrackList(String carId, Date date) {
        QueryWrapper<CarTrack> carTrackQueryWrapper = new QueryWrapper<>();
        carTrackQueryWrapper.orderByDesc("timestamp");
        carTrackQueryWrapper.eq("car_id", carId);
        carTrackQueryWrapper.lambda().le(CarTrack::getTimestamp, date);
        carTrackQueryWrapper.last("limit 200");
        List<CarTrack> carTrackList = carTrackMapper.selectList(carTrackQueryWrapper);
        Predicate<CarTrack> gtMassZERO = carTrack -> carTrack.getOilMass().compareTo(BigDecimal.ZERO) > 0;
        carTrackList = carTrackList.stream().filter(gtMassZERO).collect(Collectors.toList());
        return carTrackList;
    }


    /**
     * 判断是否在网格
     *
     * @param kfkHandleParam
     * @return
     */
    private KfkHandleParam checkInGrid(KfkHandleParam kfkHandleParam) {
        //区域类型，1标记点，2行政区域，3圆形区域，4矩形区域，5多边形区域，6自定义路段，7路段规划，8行驶轨迹规划
        boolean isInGrid = false;
        switch (kfkHandleParam.getGrid().getAreaType()) {
            case 3:
                isInGrid = DistanceUtils.insideCircle(Double.valueOf(kfkHandleParam.getCurrentCarTrack().getLng()),
                        Double.valueOf(kfkHandleParam.getCurrentCarTrack().getLat()), Double.valueOf(kfkHandleParam.getGrid().getLng()),
                        Double.valueOf(kfkHandleParam.getGrid().getLat()), kfkHandleParam.getGrid().getRadius());
                break;
            case 4:
                isInGrid = DistanceUtils.insideRect(Double.valueOf(kfkHandleParam.getCurrentCarTrack().getLng()),
                        Double.valueOf(kfkHandleParam.getCurrentCarTrack().getLat()), kfkHandleParam.getGrid().getLnglat());
                break;
            case 5:
                isInGrid = DistanceUtils.insidePolygon(Double.valueOf(kfkHandleParam.getCurrentCarTrack().getLng()),
                        Double.valueOf(kfkHandleParam.getCurrentCarTrack().getLat()), kfkHandleParam.getGrid().getLnglat());
                break;
            case 6:
                log.info("==判断坐标是否网格内(checkInGrid),gridId:{}", kfkHandleParam.getGrid().getGridId());
                isInGrid = DistanceUtils.insideLine(Double.valueOf(kfkHandleParam.getLon()), Double.valueOf(kfkHandleParam.getLat()), kfkHandleParam.getGrid().getLnglat(), kfkHandleParam.getGrid().getLineWidth());
                break;
            default:
                break;
        }
        kfkHandleParam.setIsInGrid(isInGrid);
        return kfkHandleParam;
    }

    private AbnormalResult carViolationHandle(KfkHandleParam kfkHandleParam) {
        String today = DateUtil.formatDate(kfkHandleParam.getLocationDate());
        AbnormalResult abnormalResult = new AbnormalResult();
        //两个坐标定位时间大于1小时，认为车辆当天刚开始作业，不做违规处理
        if (kfkHandleParam.getTwoPointTimeDiffer() > 60 * 60) {
            return abnormalResult;
        }
        for (WorkRuleItem workRuleItem : kfkHandleParam.getWorkRuleItems()) {
            String sysname = workRuleItem.getSysName();
            String ruleCcontent = workRuleItem.getContent();
            JSONObject contentJson = JSON.parseObject(ruleCcontent);
            //两点相差时间秒数
            Integer twoPointTimeDiffer;
            if (Objects.nonNull(kfkHandleParam.getShiftStartDate()) && Objects.nonNull(kfkHandleParam.getShiftEndDate())) {
                if (kfkHandleParam.getPreCarTrack().getTimestamp().compareTo(kfkHandleParam.getShiftStartDate()) < 0) {
                    twoPointTimeDiffer = StringUtils.calLastedTime(kfkHandleParam.getShiftStartDate(), kfkHandleParam.getCurrentCarTrack().getTimestamp());
                } else {
                    twoPointTimeDiffer = Objects.nonNull(kfkHandleParam.getTwoPointTimeDiffer()) ? kfkHandleParam.getTwoPointTimeDiffer() : 0;
                }
            } else {
                twoPointTimeDiffer = Objects.nonNull(kfkHandleParam.getTwoPointTimeDiffer()) ? kfkHandleParam.getTwoPointTimeDiffer() : 0;
            }
            switch (sysname) {
                case "超时未完成":
                    log.info("超时未完成[违规]");
                    break;
                case "未到岗":
                    log.info("未到岗[违规]");
                    break;
                case "速度限制":
                    if (0 == workRuleItem.getIsEnable()) {
                        break;
                    }
                    //不在网格内不报违规
                    if (!kfkHandleParam.getIsInGrid()) {
                        //超速违规持续时间秒
                        RedisUtil.set(CarViolationSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                        //某时间段最大速
                        RedisUtil.set(CarViolationMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                        break;
                    }

                    Double zdSpeed = Double.parseDouble(contentJson.get("zd").toString());
                    if (kfkHandleParam.getCurrentCarTrack().getStatus() == 1 && kfkHandleParam.getCurrentCarTrack().getSpeed() > zdSpeed) {
                        //某时间段最大速
                        int maxSpeed = Objects.nonNull(RedisUtil.get(CarViolationMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarViolationMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) : 0;
                        if (kfkHandleParam.getSpeed() > maxSpeed) {
                            RedisUtil.set(CarViolationMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, kfkHandleParam.getSpeed());
                        }

                        //超速持续时间秒
                        int carViolationSpeedTime = Objects.nonNull(RedisUtil.get(CarViolationSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarViolationSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                        RedisUtil.set(CarViolationSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carViolationSpeedTime);

                        abnormalResult = saveCarViolation(kfkHandleParam, workRuleItem, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * twoPointTimeDiffer));

                        kfkHandleParam.getCurrentCarTrack().setIsWarning(1);
                        kfkHandleParam.getCurrentCarTrack().setWarningOverSpeed(kfkHandleParam.getPreCarTrack().getWarningOverSpeed() + kfkHandleParam.getTwoPointTimeDiffer());
                        kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());
                        kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("warningOverSpeed");

                        abnormalResult.setIsSpeedLimit(1);

                        if (2 == abnormalResult.getIskeep()) {
                            // 发送违规信息到前台
                            sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_VIOLATION, sysname, "超速违规");
                        }
                    } else {
                        //超速违规持续时间秒
                        RedisUtil.set(CarViolationSpeedTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                        //某时间段最大速
                        RedisUtil.set(CarViolationMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                    }
                    PerformanceMonitor.end();
                    break;
                case "油量监测":
                    //油量检测：超出20%（判断作业中的油量，采用最简单的方式，取上次油量，计算中间路程，计算油耗）
                    //距离 last2now_distance
                    //油量差 kfkHandleParam.getCurrentCarTrack().getOilMass()-LastCarTrack.getOilMass()
                    // TODO 后续改为作业完成后判断
                    //                    Double ccl = Double.parseDouble(contentJson.get("ccl").toString()) / 100;
                    //                    double oilDistance = kfkHandleParam.getPreCarTrack().getOilMass() - kfkHandleParam.getCurrentCarTrack().getOilMass();
                    //                    if (oilDistance > 0) {
                    //                        if (kfkHandleParam.getTwoPointDistanceDiffer() > 0) {
                    //                            //油耗比例=计划油耗(单位距离油耗) ÷ 实际油耗
                    //                            double deplete = (kfkHandleParam.getWorkPlan().getEstimateOil().doubleValue() / (kfkHandleParam.getGrid().getKm() * 1000)) / (oilDistance / kfkHandleParam.getTwoPointDistanceDiffer());
                    //                            if (deplete >= 1 + ccl) {
                    //                                kfkHandleParam.getCurrentCarTrack().setIsWarning(1);
                    //                                kfkHandleParam.getCurrentCarTrack().setWarningOil(kfkHandleParam.getPreCarTrack().getWarningOil() + kfkHandleParam.getTwoPointTimeDiffer());
                    //                                kfkHandleParam.getCurrentCarTrack().setMessage("油量检测违规");
                    //                                kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("warningOil");
                    //                                String violationDesc = "油量检测违规,超出计划油量";
                    //                                CarViolation carViolation = saveCarViolation(kfkHandleParam, workRuleItem, violationDesc);
                    //                                // 发送违规信息到前台
                    //                                sendAlarm(kfkHandleParam, carViolation.getCarViolationId(), CommonConstant.PUSH_TYPE_VIOLATION, sysname, carViolation.getRuleTypeName());
                    //                            }
                    //                        }
                    //                    }
                    break;
                case "离岗":
                    if (0 == workRuleItem.getIsEnable()) {
                        break;
                    }
                    //不在网格内不报违规
                    if (!kfkHandleParam.getIsInGrid()) {
                        //该人员违规离岗的持续时间
                        RedisUtil.set(CarViolationDemobilizTimeKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, 0);
                        //该人员违规是否在网格内
                        RedisUtil.set(PersonViolationInGridFlagKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, 1);
                        break;
                    }
                    //允许出多少次
                    Integer yxc = Objects.nonNull(contentJson.get("yxc")) ? Integer.parseInt(contentJson.get("yxc").toString()) : 2;
                    //出网格判定多少秒
                    Integer cwgpd = Objects.nonNull(contentJson.get("cwgpd")) ? Integer.parseInt(contentJson.get("cwgpd").toString()) * 60 : 20 * 60;
                    //单次最长多少秒
                    Integer dczc = Objects.nonNull(contentJson.get("dczc")) ? Integer.parseInt(contentJson.get("dczc").toString()) * 60 : 5 * 60;

                    /*离岗：单次考勤时间段内：
                    单次最长时间内，则不报警，次数不限；
                    单次最长时间外 至 出网格判断时间内，允许2次机会，超过机会后报警；
                    超过出网格判断时间，则立即报警。*/
                    if (!kfkHandleParam.getIsInGrid()) {
                        //离岗违规持续时间秒
                        int personViolationDemobilizTime = Objects.nonNull(RedisUtil.get(CarViolationDemobilizTimeKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class)) ? RedisUtil.get(CarViolationDemobilizTimeKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                        RedisUtil.set(CarViolationDemobilizTimeKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, personViolationDemobilizTime);

                        if (personViolationDemobilizTime >= cwgpd) {
                            abnormalResult = saveCarViolation(kfkHandleParam, workRuleItem, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * twoPointTimeDiffer));

                            kfkHandleParam.getCurrentCarTrack().setIsWarning(1);
                            kfkHandleParam.getCurrentCarTrack().setIsDemobiliz(1);
                            kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("warningDemobiliz");
                            kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());

                            abnormalResult.setIsEmptyTravel(1);

                            if (2 == abnormalResult.getIskeep()) {
                                sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_VIOLATION, sysname, "车辆离岗");
                            }
                        } else if (personViolationDemobilizTime > dczc && personViolationDemobilizTime < cwgpd) {

                            //该人员正常在网格的次数
                            int personViolationInGridFlag = Objects.nonNull(RedisUtil.get(PersonViolationInGridFlagKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class)) ? RedisUtil.get(PersonViolationInGridFlagKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class) : 1;
                            if (1 == personViolationInGridFlag) {
                                //该人员违规是否在网格内
                                RedisUtil.set(PersonViolationInGridFlagKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, 0);
                                //该人员当次考勤不在网格的次数
                                RedisUtil.set(PersonViolationNotInGridNumKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, (Objects.nonNull(RedisUtil.get(PersonViolationNotInGridNumKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class)) ? RedisUtil.get(PersonViolationNotInGridNumKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class) + 1 : 1));
                            }
                            int personViolationNotInGridNum = Objects.nonNull(RedisUtil.get(PersonViolationNotInGridNumKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class)) ? RedisUtil.get(PersonViolationNotInGridNumKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, int.class) + 1 : 1;
                            if (personViolationNotInGridNum > yxc) {
                                abnormalResult = saveCarViolation(kfkHandleParam, workRuleItem, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * twoPointTimeDiffer));

                                kfkHandleParam.getCurrentCarTrack().setIsWarning(1);
                                kfkHandleParam.getCurrentCarTrack().setIsDemobiliz(1);
                                kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("warningDemobiliz");
                                kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());

                                abnormalResult.setIsEmptyTravel(1);

                                if (2 == abnormalResult.getIskeep()) {
                                    sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_VIOLATION, sysname, "车辆离岗");
                                }
                            }
                        }
                    } else {
                        //该人员违规离岗的持续时间
                        RedisUtil.set(CarViolationDemobilizTimeKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, 0);
                        //该人员违规是否在网格内
                        RedisUtil.set(PersonViolationInGridFlagKeyToday.token, kfkHandleParam.getCarId() + kfkHandleParam.getWorkKaoqin().getWorkKaoqinId() + "_" + today, 1);
                    }
                    PerformanceMonitor.end();
                    break;
                case "车辆空驶":
                    if (0 == workRuleItem.getIsEnable()) {
                        break;
                    }
                    //不在网格内不报违规
                    if (!kfkHandleParam.getIsInGrid()) {
                        //空驶违规持续时间秒
                        RedisUtil.set(CarViolationEmptyTravelTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                        break;
                    }
                    //空驶：喷头未开启10分钟，扫盘未落地12分钟（如果status连续10分钟持续未开启，则判断空驶）{"spwld":12,"ptwkq":10}
                    //扫盘未落地
                    Integer spwldTime = Integer.parseInt(contentJson.get("spwld").toString());
                    //喷头未开启
                    Integer ptwkqTime = Integer.parseInt(contentJson.get("ptwkq").toString());
                    Integer limitTime = 0;
                    if ("洒水车".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = ptwkqTime;
                    } else if ("机扫车".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = spwldTime;
                    } else if ("除雪车".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = spwldTime;
                    } else if ("收集车".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = spwldTime;
                    } else if ("转运车".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = spwldTime;
                    } else if ("管理车".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = spwldTime;
                    } else if ("撒布机".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = spwldTime;
                    } else if ("雾炮车".equals(kfkHandleParam.getTlCarType().getTypename())) {
                        limitTime = spwldTime;
                    }

                    if (kfkHandleParam.getCurrentCarTrack().getStatus() == 0 && !kfkHandleParam.getIfStay() && limitTime > 0) {
//                        Integer emptyMoveSecondTime = kfkHandleParam.getPreCarTrack().getWarningDriveEmpty() + kfkHandleParam.getTwoPointTimeDiffer();
//                        kfkHandleParam.getCurrentCarTrack().setWarningDriveEmpty(emptyMoveSecondTime);

                        //空驶违规持续时间秒
                        int carViolationEmptyTravelTime = Objects.nonNull(RedisUtil.get(CarViolationEmptyTravelTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarViolationEmptyTravelTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                        RedisUtil.set(CarViolationEmptyTravelTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carViolationEmptyTravelTime);

                        if (carViolationEmptyTravelTime >= limitTime * 60) {

                            abnormalResult = saveCarViolation(kfkHandleParam, workRuleItem, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * twoPointTimeDiffer));

                            kfkHandleParam.getCurrentCarTrack().setIsWarning(1);
                            kfkHandleParam.getCurrentCarTrack().setIsEmptyTravel(1);
                            kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("warningDriveEmpty");
                            kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());

                            abnormalResult.setIsEmptyTravel(1);

                            if (2 == abnormalResult.getIskeep()) {
                                // 发送违规信息到前台
                                sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_VIOLATION, sysname, "车辆空驶");
                            }
                        }
                    } else {
                        //空驶违规持续时间秒
                        RedisUtil.set(CarViolationEmptyTravelTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                    }
                    PerformanceMonitor.end();
                    break;
                case "车辆停留":
                    if (0 == workRuleItem.getIsEnable()) {
                        break;
                    }
                    //不在网格内不报违规
                    if (!kfkHandleParam.getIsInGrid()) {
                        //停留违规持续时间秒
                        RedisUtil.set(CarViolationStopTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                        break;
                    }
                    //停留时间限制，分钟转为秒数
                    Integer tl = Integer.parseInt(contentJson.get("tl").toString());
                    //停留
                    if (kfkHandleParam.getIfStay()) {

                        //停留违规持续时间秒
                        int carViolationStopTime = Objects.nonNull(RedisUtil.get(CarViolationStopTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarViolationStopTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) + twoPointTimeDiffer : twoPointTimeDiffer;
                        RedisUtil.set(CarViolationStopTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, carViolationStopTime);

                        if (carViolationStopTime >= tl * 60) {
                            abnormalResult = saveCarViolation(kfkHandleParam, workRuleItem, new Date(kfkHandleParam.getLocationDate().getTime() - 1000 * tl * 60));

                            kfkHandleParam.getCurrentCarTrack().setIsWarning(1);
                            kfkHandleParam.getCurrentCarTrack().setLastMessageCheck("warningStay");
                            kfkHandleParam.getCurrentCarTrack().setMessage(abnormalResult.getMessage());
                            kfkHandleParam.getCurrentCarTrack().setIsStopViolation(1);

                            abnormalResult.setIsStop(1);

                            if (2 == abnormalResult.getIskeep()) {
                                // 发送违规信息到前台
                                sendAlarm(kfkHandleParam, abnormalResult.getId(), CommonConstant.PUSH_TYPE_VIOLATION, sysname, "车辆停留");
                            }
                        }
                    } else {
                        //停留违规持续时间秒
                        RedisUtil.set(CarViolationStopTimeKeyToday.token, kfkHandleParam.getCarId() + "_" + today, 0);
                    }
                    PerformanceMonitor.end();
                    break;
                case "非法倾倒":
                    log.info("非法倾倒[违规]");
                    break;
                case "水量监测":
                    log.info("水量监测[违规]");
                    break;
                case "作业遗留":
                    log.info("作业遗留[违规]");
                    break;
                case "晚到":
                    log.info("晚到[违规]");
                    break;
                default:
                    break;
            }
        }
        return abnormalResult;
    }

    /**
     * 获取车辆邮箱容积
     *
     * @param tlCar
     * @return
     */
    private Integer getOilVolume(TlCar tlCar) {
        String tankvolcheck = tlCar.getTankvolcheck();
        if (StringUtils.isEmpty(tankvolcheck)) {
            QueryWrapper<TlCarModel> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TlCarModel::getId, tlCar.getCarmodelid());
            TlCarModel tlCarModel = tlCarModelMapper.selectOne(queryWrapper);
            if (tlCarModel == null) {
                return 75;
            } else {
                return (null == tlCarModel.getTankvolume() ? 75 : tlCarModel.getTankvolume());
            }
        }
        return Integer.parseInt(tankvolcheck);
    }

    /**
     * @param kfkHandleParam
     * @param targetId
     * @param model(推送类型 1事件2报警3违规)
     * @param sysname
     * @param alarmTypeName
     */
    private void sendAlarm(KfkHandleParam kfkHandleParam, String targetId, Integer model, String sysname, String alarmTypeName) {
        QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        List<SysUserRole> sysUserRoleList = sysUserRoleMapper.selectList(sysUserRoleQueryWrapper);
        Map<String, List<SysUserRole>> sysUserRoleMap = sysUserRoleList.stream().collect(Collectors.groupingBy(SysUserRole::getUserid));

        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        List<SysRole> sysRoleList = sysRoleMapper.selectList(sysRoleQueryWrapper);
        Map<String, SysRole> sysRoleMap = sysRoleList.stream().collect(Collectors.groupingBy(SysRole::getId, Collectors.collectingAndThen(toList(), values -> values.get(0))));

        String remindKey = AlarmUtils.changeCarAlarmName(sysname);
        JSONObject alarmJson = new JSONObject();
        alarmJson.put("model", model);
        JSONObject detailJson = new JSONObject();
        detailJson.put("id", targetId);
        detailJson.put("remindKey", remindKey);
        detailJson.put("happenTime", DateUtil.formatDateTime(kfkHandleParam.getLocationDate()));
        detailJson.put("lng", kfkHandleParam.getLon());
        detailJson.put("lat", kfkHandleParam.getLat());
        detailJson.put("address", kfkHandleParam.getCurrentAddress());
        detailJson.put("pic", kfkHandleParam.getTlCar().getCarpicture());
        detailJson.put("typeId", kfkHandleParam.getTlCarType().getId());
        detailJson.put("typeName", alarmTypeName);
        detailJson.put("authorId", kfkHandleParam.getTlCar().getId());
        detailJson.put("authorName", kfkHandleParam.getTlCar().getCarnumber());
        detailJson.put("authorType", "car");
        alarmJson.put("detail", detailJson);
//        List<SysUserRole> sysUserRoleList2 = sysUserRoleMap.get(user1.getUid());
//        if (null != sysUserRoleList2) {
//            for (SysUserRole sysUserRole : sysUserRoleList2) {
//                SysRole sysRole = sysRoleMap.get(sysUserRole.getRoleid());
//                if (null != sysRole) {
//                    if (!sysRole.getRoleName().equals("管理员")) {

//                    }
//                }
//            }
//        }

        TlEmployee tlEmployee = tlEmployeeMapper.selectById(kfkHandleParam.getTlCar().getDriverid());
        if (null != tlEmployee) {

            WebSocketUtils.sendMessageToOne(alarmJson.toString(), tlEmployee.getBindaccount());

            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.lambda().notIn(User::getUid, tlEmployee.getBindaccount());
            List<User> userList = userMapper.selectList(userQueryWrapper);

            userList.forEach(user -> {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("model", model);
                JSONObject object = new JSONObject();
                object.put("id", targetId);
                object.put("remindKey", remindKey);
                object.put("happenTime", DateUtil.formatDateTime(kfkHandleParam.getLocationDate()));
                object.put("lng", kfkHandleParam.getLon());
                object.put("lat", kfkHandleParam.getLat());
                object.put("address", kfkHandleParam.getCurrentAddress());
                object.put("pic", kfkHandleParam.getTlCar().getCarpicture());
                object.put("typeId", kfkHandleParam.getTlCarType().getId());
                object.put("typeName", alarmTypeName);
                object.put("authorId", kfkHandleParam.getTlCar().getId());
                object.put("authorName", kfkHandleParam.getTlCar().getCarnumber());
                object.put("authorType", "car");
                jsonObject.put("detail", object);
                List<SysUserRole> sysUserRoleList1 = sysUserRoleMap.get(user.getUid());
                if (null != sysUserRoleList1) {
                    for (SysUserRole sysUserRole : sysUserRoleList1) {
                        SysRole sysRole = sysRoleMap.get(sysUserRole.getRoleid());
                        if (null != sysRole) {
                            if (sysRole.getRoleName().equals("管理员")) {
                                WebSocketUtils.sendMessageToOne(jsonObject.toString(), sysUserRole.getUserid());
                            }
                        }
                    }
                }
            });
        }
    }

    public AbnormalResult saveAlarmCar(KfkHandleParam kfkHandleParam, TlThreshold tlThreshold, Date alarmStartTime) {
        String today = DateUtil.formatDate(alarmStartTime);

        AlarmCar alarmCar = RedisUtil.get(CarAlarmTypeNameLastOneKeyToday.token, kfkHandleParam.getCarId() + "_" + tlThreshold.getSysname() + "_" + today, AlarmCar.class);
        if (Objects.isNull(alarmCar)) {
            String day = DateUtil.formatDate(alarmStartTime);
            String startTime = AttributeUtils.timeCompletion(day, 's');
            String endTime = AttributeUtils.timeCompletion(day, 'e');

            QueryWrapper<AlarmCar> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(AlarmCar::getCarId, kfkHandleParam.getCarId());
            queryWrapper.lambda().eq(AlarmCar::getAlarmTypeName, tlThreshold.getSysname());
            queryWrapper.lambda().between(AlarmCar::getAlarmTime, startTime, endTime);
            queryWrapper.lambda().orderByDesc(AlarmCar::getAlarmTime);
            queryWrapper.lambda().last(" LIMIT 1");
            alarmCar = alarmCarMapper.selectOne(queryWrapper);
        }

        if (Objects.nonNull(alarmCar)) {
            //获取基数天数和检测时间间隔
            //聚合时间(分钟)
            int polymerizationtime = 0;
            if (Objects.nonNull(tlThreshold.getPolymerizationtime())) {
                polymerizationtime = tlThreshold.getPolymerizationtime();
            }
            Date date1 = new Date(alarmStartTime.getTime() - 1000 * 60 * polymerizationtime);
            if (date1.compareTo(alarmCar.getAlarmEndTime()) > 0) {
                alarmCar = null;
            }
        }

        AbnormalResult abnormalResult = new AbnormalResult();
        if (Objects.nonNull(alarmCar)) {
            //过滤掉之前的时间
            if (kfkHandleParam.getLocationDate().compareTo(alarmCar.getAlarmEndTime()) <= 0) {
                return abnormalResult;
            }

            abnormalResult = updateCarAlarm(kfkHandleParam, alarmCar);
        }
        if (1 != abnormalResult.getIskeep()) {
            abnormalResult = insertCarAlarm(kfkHandleParam, tlThreshold, alarmStartTime);
        }
        return abnormalResult;
    }

    /**
     * 更新车辆报警异常表
     *
     * @param kfkHandleParam
     * @param oilMassThreshold
     * @param alarmStartTime
     * @return
     */
    private AbnormalResult insertCarAlarm(KfkHandleParam kfkHandleParam, TlThreshold oilMassThreshold, Date alarmStartTime) {
        AbnormalResult abnormalResult = new AbnormalResult();
        String today = DateUtil.formatDate(alarmStartTime);
        AlarmCar alarmCar1 = RedisUtil.get(CarAlarmTypeNameLastOneKeyToday.token, kfkHandleParam.getCarId() + "_" + oilMassThreshold.getSysname() + "_" + today, AlarmCar.class);
        if (Objects.nonNull(alarmCar1) && alarmCar1.getAlarmTime().compareTo(kfkHandleParam.getLocationDate()) == 0) {
            abnormalResult.setMessage(alarmCar1.getContent());
            return abnormalResult;
        }

        AlarmCar alarmCar = new AlarmCar();
        alarmCar.setAlarmCarId(StringUtils.uuid());
        alarmCar.setCarId(kfkHandleParam.getCarId());
        alarmCar.setCarName(kfkHandleParam.getTlCar().getCarnumber());
        alarmCar.setDepId(kfkHandleParam.getTlCar().getCardeptid());

        SysDepart sysDepart = sysDepartMapper.selectById(kfkHandleParam.getTlCar().getCardeptid());
        if (Objects.nonNull(sysDepart)) {
            alarmCar.setDepName(sysDepart.getDepartName());
        }
        alarmCar.setAlarmTypeId(oilMassThreshold.getId());
        alarmCar.setAlarmTypeName(oilMassThreshold.getSysname());
        alarmCar.setLng(kfkHandleParam.getLon());
        alarmCar.setLat(kfkHandleParam.getLat());
        alarmCar.setAddress(kfkHandleParam.getCurrentAddress());
        alarmCar.setAlarmTime(kfkHandleParam.getLocationDate());
        alarmCar.setCreateTime(kfkHandleParam.getCurrentSystemDate());
        alarmCar.setAlarmStartTime(alarmStartTime);
        alarmCar.setAlarmEndTime(kfkHandleParam.getLocationDate());

        alarmCar.setCarTrackStartId(kfkHandleParam.getCarTrackId());
        alarmCar.setCarTrackEndId(kfkHandleParam.getCarTrackId());
        //持续时间秒
        int duration = StringUtils.calLastedTime(alarmCar.getAlarmStartTime(), kfkHandleParam.getLocationDate());
        String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));
        String dangerDesc = "";

        if ("超速".equals(alarmCar.getAlarmTypeName())) {
            //某时间段最大速
            int maxSpeed = Objects.nonNull(RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, kfkHandleParam.getCarId() + "_" + today, int.class) : 0;
            dangerDesc = alarmCar.getAlarmTypeName() + "时长" + time + ",最高速度" + maxSpeed + "km/h";
            alarmCar.setAlarmValue(new BigDecimal(String.valueOf(maxSpeed)));

            //保存更新后的持续保持时间
            RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, alarmCar.getCarId() + "_" + today, duration);
        }
        if ("漏油".equals(alarmCar.getAlarmTypeName())) {

            Map consumptionPer = getConsumptionPer(kfkHandleParam.getCarId(), StringUtils.DateFormat(alarmStartTime), StringUtils.DateFormat(kfkHandleParam.getLocationDate()));
            //获取时间间隔的总耗油
            BigDecimal oilMassSum = new BigDecimal(String.valueOf(consumptionPer.get("oilMassSum")));
            //获取时间间隔的总里程数
            BigDecimal mileageSum = new BigDecimal(String.valueOf(consumptionPer.get("mileageSum")));
            //获取检测时间间隔的百公里油耗
            BigDecimal timeintervalConsumptionPer = new BigDecimal(String.valueOf(consumptionPer.get("consumptionPer")));
            timeintervalConsumptionPer = timeintervalConsumptionPer.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
            abnormalResult.setValue(timeintervalConsumptionPer);

            //调用小曹的接口获取list, 并用该list作为参数, 调用小曹方法获取值后更新到数据库内
            Date date = new Date(Tools.getDateAddDay(new Date(), -1));
            List<StateOilDevice> listBeginSevenDay = carTrackService.getStateOilDevices(kfkHandleParam.getCarId(), date);
            //平均油耗计算方法
            Predicate<StateOilDevice> notIsToday = stateOilDevice -> !Tools.isSameDay(stateOilDevice.getDeviceDate(), date);
            List<StateOilDevice> notIsTodayList = listBeginSevenDay.stream().filter(notIsToday).collect(Collectors.toList());
            BigDecimal averageOil = carTrackService.getAlarmOilWearNum(notIsTodayList, mileageSum.multiply(new BigDecimal("1000")));
            BigDecimal subtract = oilMassSum.subtract(averageOil);
            alarmCar.setOilLeakageValue(subtract);

            dangerDesc = alarmCar.getAlarmTypeName() + "时长" + time + ",总里程数为" + mileageSum + "公里, 总漏油值" + oilMassSum + "升";

            alarmCar.setAlarmValue(oilMassSum);
        }

        //根据carId查询type
        TlCar tlCar = tlCarMapper.selectById(kfkHandleParam.getCarId());
        String typeId = "";
        String typeName = "";
        if (Objects.nonNull(tlCar) && StringUtils.isNotEmpty(tlCar.getCartypeid())) {
            typeId = tlCar.getCartypeid();
            TlCarType tlCarType = tlCarTypeService.getFromRedis(tlCar.getCartypeid());
            if (Objects.nonNull(tlCarType) && StringUtils.isNotEmpty(tlCarType.getTypename())) {
                typeName = tlCarType.getTypename();
            }
        }
        alarmCar.setContent(dangerDesc);
        alarmCar.setCarTypeId(typeId);
        alarmCar.setCarTypeName(typeName);
        int insert = alarmCarMapper.insert(alarmCar);
        if (insert > 0) {
            abnormalResult.setIskeep(2);
        }

        abnormalResult.setId(alarmCar.getAlarmCarId());
        abnormalResult.setMessage(alarmCar.getContent());

        //保存插入后的数据
        RedisUtil.set(CarAlarmTypeNameLastOneKeyToday.token, alarmCar.getCarId() + "_" + alarmCar.getAlarmTypeName() + "_" + today, alarmCar);
        return abnormalResult;
    }

    /**
     * 更新车辆违规异常表
     *
     * @param kfkHandleParam
     * @param workRuleItem
     * @param alarmStartTime
     * @return
     */
    private AbnormalResult insertCarViolation(KfkHandleParam kfkHandleParam, WorkRuleItem workRuleItem, Date alarmStartTime) {
        AbnormalResult abnormalResult = new AbnormalResult();
        String today = DateUtil.formatDate(alarmStartTime);
        CarViolation carViolation1 = RedisUtil.get(CarViolationTypeNameLastOneKeyToday.token, kfkHandleParam.getCarId() + "_" + workRuleItem.getSysName() + "_" + today, CarViolation.class);

        if (Objects.nonNull(carViolation1) && carViolation1.getTime().compareTo(kfkHandleParam.getLocationDate()) == 0) {
            abnormalResult.setMessage(carViolation1.getContent());
            return abnormalResult;
        }

        CarViolation carViolation = new CarViolation();
        carViolation.setCarId(kfkHandleParam.getCarId());
        carViolation.setCarViolationId(StringUtils.uuid());
        carViolation.setCarName(kfkHandleParam.getTlCar().getCarnumber());
        carViolation.setCarTypeId(kfkHandleParam.getTlCar().getCartypeid());
        carViolation.setCarTypeName(kfkHandleParam.getTlCarType().getTypename());
        carViolation.setDepid(kfkHandleParam.getTlCar().getCardeptid());
        carViolation.setDepName(kfkHandleParam.getTlCar().getCardeptname());

        carViolation.setRuleTypeId(workRuleItem.getWorkRuleItemId());
        carViolation.setRuleTypeName(workRuleItem.getSysName());
        carViolation.setTime(kfkHandleParam.getLocationDate());
        carViolation.setLng(kfkHandleParam.getLon());
        carViolation.setLat(kfkHandleParam.getLat());
        carViolation.setAddress(kfkHandleParam.getCurrentAddress());
        carViolation.setCreateTime(kfkHandleParam.getCurrentSystemDate());
        carViolation.setGridId(kfkHandleParam.getGrid().getGridId());
        carViolation.setModule(kfkHandleParam.getWorkPlan().getType());
        carViolation.setIsStopViolation(kfkHandleParam.getCurrentCarTrack().getIsStopViolation());
        carViolation.setViolationStartTime(alarmStartTime);
        carViolation.setViolationEndTime(kfkHandleParam.getLocationDate());

        int duration = StringUtils.calLastedTime(carViolation.getViolationStartTime(), kfkHandleParam.getLocationDate());
        String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));
        String dangerDesc = "";

        carViolation.setCarTrackStartId(kfkHandleParam.getCarTrackId());
        carViolation.setCarTrackEndId(kfkHandleParam.getCarTrackId());

        if ("车辆停留".equals(carViolation.getRuleTypeName())) {
            dangerDesc = "车辆停留违规, 停留时长" + time;
            carViolation.setViolationValue(new BigDecimal(duration));
        }
        if ("速度限制".equals(carViolation.getRuleTypeName())) {
            //超速最大速度
            int maxSpeed = Objects.nonNull(RedisUtil.get(CarViolationMaxSpeedKeyToday.token, carViolation.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarViolationMaxSpeedKeyToday.token, carViolation.getCarId() + "_" + today, int.class) : 0;
            carViolation.setViolationValue(new BigDecimal(String.valueOf(maxSpeed)));

            dangerDesc = "超速违规时长" + time + ",最高速度" + maxSpeed + "km/h";
        }
        if ("车辆空驶".equals(carViolation.getRuleTypeName())) {
            dangerDesc = "车辆空驶违规,空驶时长" + time;
            carViolation.setViolationValue(new BigDecimal(duration));
        }

        carViolation.setContent(dangerDesc);
        int insert = carViolationMapper.insert(carViolation);
        if (insert > 0) {
            abnormalResult.setIskeep(2);
        }
        abnormalResult.setId(carViolation.getCarViolationId());
        abnormalResult.setMessage(dangerDesc);

        //保存插入后的数据
        RedisUtil.set(CarViolationTypeNameLastOneKeyToday.token, carViolation.getCarId() + "_" + carViolation.getRuleTypeName() + "_" + today, carViolation);
        return abnormalResult;
    }

    /**
     * 更新报警信息
     *
     * @param alarmCar
     */
    private AbnormalResult updateCarAlarm(KfkHandleParam kfkHandleParam, AlarmCar alarmCar) {
        AbnormalResult abnormalResult = new AbnormalResult();
        String today = DateUtil.formatDate(alarmCar.getAlarmStartTime());
        int duration = StringUtils.calLastedTime(alarmCar.getAlarmStartTime(), kfkHandleParam.getLocationDate());
        String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));

        alarmCar.setCarTrackEndId(kfkHandleParam.getCarTrackId());

        String dangerDesc = "";
        if ("超速".equals(alarmCar.getAlarmTypeName())) {
            //某时间段最大速
            int maxSpeed = Objects.nonNull(RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, alarmCar.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarAlarmMaxSpeedKeyToday.token, alarmCar.getCarId() + "_" + today, int.class) : 0;
            dangerDesc = alarmCar.getAlarmTypeName() + "时长" + time + ",最高速度" + maxSpeed + "km/h";
            alarmCar.setContent(dangerDesc);
            alarmCar.setAlarmEndTime(kfkHandleParam.getLocationDate());
            alarmCar.setIsKeep(1);
            alarmCar.setAlarmValue(new BigDecimal(String.valueOf(maxSpeed)));

            int i = alarmCarMapper.updateById(alarmCar);

            abnormalResult.setId(alarmCar.getAlarmCarId());
            abnormalResult.setMessage(dangerDesc);
            abnormalResult.setIskeep(i);

            //保存更新后的持续保持时间
            RedisUtil.set(CarAlarmSpeedTimeKeyToday.token, alarmCar.getCarId() + "_" + today, duration);
            //保存更新后的数据
            RedisUtil.set(CarAlarmTypeNameLastOneKeyToday.token, alarmCar.getCarId() + "_" + alarmCar.getAlarmTypeName() + "_" + today, alarmCar);
        }
        if ("漏油".equals(alarmCar.getAlarmTypeName())) {

            Map consumptionPer = getConsumptionPer(kfkHandleParam.getCarId(), StringUtils.DateFormat(alarmCar.getAlarmStartTime()), StringUtils.DateFormat(kfkHandleParam.getLocationDate()));
            //获取时间间隔的总耗油
            BigDecimal oilMassSum = new BigDecimal(String.valueOf(consumptionPer.get("oilMassSum")));
            //获取时间间隔的总里程数
            BigDecimal mileageSum = new BigDecimal(String.valueOf(consumptionPer.get("mileageSum")));

            //获取检测时间间隔的百公里油耗
            BigDecimal timeintervalConsumptionPer = new BigDecimal(String.valueOf(consumptionPer.get("consumptionPer")));
            timeintervalConsumptionPer = timeintervalConsumptionPer.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
            abnormalResult.setValue(timeintervalConsumptionPer);

            //调用小曹的接口获取list, 并用该list作为参数, 调用小曹方法获取值后更新到数据库内
            Date date = new Date(Tools.getDateAddDay(new Date(), -1));
            List<StateOilDevice> listBeginSevenDay = carTrackService.getStateOilDevices(kfkHandleParam.getCarId(), date);
            //平均油耗计算方法
            Predicate<StateOilDevice> notIsToday = stateOilDevice -> !Tools.isSameDay(stateOilDevice.getDeviceDate(), date);
            List<StateOilDevice> notIsTodayList = listBeginSevenDay.stream().filter(notIsToday).collect(Collectors.toList());
            BigDecimal averageOil = carTrackService.getAlarmOilWearNum(notIsTodayList, mileageSum.multiply(new BigDecimal("1000")));
            BigDecimal subtract = oilMassSum.subtract(averageOil);
            alarmCar.setOilLeakageValue(subtract);

            dangerDesc = alarmCar.getAlarmTypeName() + "时长" + time + ",总里程数为" + mileageSum + "公里, 总漏油值" + oilMassSum + "升";

            alarmCar.setContent(dangerDesc);
            alarmCar.setAlarmEndTime(kfkHandleParam.getLocationDate());
            alarmCar.setIsKeep(1);
            alarmCar.setAlarmValue(oilMassSum);

            int i = alarmCarMapper.updateById(alarmCar);

            abnormalResult.setId(alarmCar.getAlarmCarId());
            abnormalResult.setMessage(dangerDesc);
            abnormalResult.setIskeep(i);

            //保存更新后的数据
            RedisUtil.set(CarAlarmTypeNameLastOneKeyToday.token, alarmCar.getCarId() + "_" + alarmCar.getAlarmTypeName() + "_" + today, alarmCar);
        }
        return abnormalResult;
    }

    /**
     * 车辆违规根据异常名称更新异常结束时间
     *
     * @param carViolation
     */
    private AbnormalResult updateCarViolation(KfkHandleParam kfkHandleParam, CarViolation carViolation) {
        AbnormalResult abnormalResult = new AbnormalResult();
        String dangerDesc = "";
        String today = DateUtil.formatDate(kfkHandleParam.getLocationDate());
        int duration = StringUtils.calLastedTime(carViolation.getViolationStartTime(), kfkHandleParam.getLocationDate());
        String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));

        carViolation.setCarTrackEndId(kfkHandleParam.getCarTrackId());

        if ("车辆停留".equals(carViolation.getRuleTypeName())) {
            dangerDesc = "车辆停留违规, 停留时长" + time;
            carViolation.setViolationValue(new BigDecimal(duration));
        }
        if ("速度限制".equals(carViolation.getRuleTypeName())) {
            //超速最大速度
            int maxSpeed = Objects.nonNull(RedisUtil.get(CarViolationMaxSpeedKeyToday.token, carViolation.getCarId() + "_" + today, int.class)) ? RedisUtil.get(CarViolationMaxSpeedKeyToday.token, carViolation.getCarId() + "_" + today, int.class) : 0;
            carViolation.setViolationValue(new BigDecimal(String.valueOf(maxSpeed)));

            dangerDesc = "超速违规时长" + time + ",最高速度" + maxSpeed + "km/h";
        }
        if ("车辆空驶".equals(carViolation.getRuleTypeName())) {
            dangerDesc = "车辆空驶违规,空驶时长" + time;
            carViolation.setViolationValue(new BigDecimal(duration));
        }
        carViolation.setContent(dangerDesc);
        carViolation.setViolationEndTime(kfkHandleParam.getLocationDate());

        int i = carViolationMapper.updateById(carViolation);
        carViolation.setIsKeep(i);
        RedisUtil.set(CarViolationTypeNameLastOneKeyToday.token, kfkHandleParam.getCarId() + "_" + carViolation.getRuleTypeName() + "_" + today, carViolation);

        abnormalResult.setId(carViolation.getCarViolationId());
        abnormalResult.setMessage(dangerDesc);
        abnormalResult.setIskeep(i);
        return abnormalResult;
    }

    /**
     * 设施根据异常名称更新异常结束时间
     *
     * @param alarmSheshi
     * @param date
     * @param value
     */
    private AbnormalResult updateFacilities(AlarmSheshi alarmSheshi, Date date, BigDecimal value) {
        AbnormalResult abnormalResult = new AbnormalResult();
        String day = DateUtil.formatDate(date);
        int duration = StringUtils.calLastedTime(alarmSheshi.getAlarmStartTime(), date);
        String time = StringUtils.s2date(Long.parseLong(String.valueOf(duration)));

        if (Objects.isNull(alarmSheshi.getAlarmValue()) || value.compareTo(alarmSheshi.getAlarmValue()) > 0) {
            alarmSheshi.setAlarmValue(value);
        }

        String dangerDesc = "";
        if ("开盖报警".equals(alarmSheshi.getAlarmTypeName()) || "水位超限".equals(alarmSheshi.getAlarmTypeName())) {
            dangerDesc = alarmSheshi.getAlarmTypeName() + ", 持续时长" + time;
        } else {
            dangerDesc = alarmSheshi.getAlarmTypeName() + "时长" + time + "，报警最高浓度为" + value + "ppm";
        }
        alarmSheshi.setContent(dangerDesc);
        alarmSheshi.setAlarmEndTime(date);

        int i = alarmSheshiMapper.updateById(alarmSheshi);
        alarmSheshi.setIsKeep(i);

        RedisUtil.set(FacilitiesAlarmTypeNameLastOneKeyToday.token, alarmSheshi.getSheshiId() + "_" + alarmSheshi.getAlarmTypeName() + "_" + day, alarmSheshi);

        abnormalResult.setId(alarmSheshi.getAlarmSheshiId());
        abnormalResult.setMessage(dangerDesc);
        abnormalResult.setIskeep(i);
        return abnormalResult;
    }

    /**
     * 获取某个时间点的车辆油耗和公里数
     *
     * @return
     */
    public Map getConsumptionPer(String carId, String starttime, String endtime) {
        Map map = new HashMap();
        //总油耗
        BigDecimal oilMassSum = BigDecimal.ZERO;
        //总里程
        BigDecimal mileageSum = BigDecimal.ZERO;
        //平均消耗量
        BigDecimal consumptionPer = BigDecimal.ZERO;
        //获取平均值
//        JSONObject params = new JSONObject();
//        params.put("carId", carId);
//        params.put("starttime", starttime);
//        params.put("endtime", endtime);
        MileageAndOilWearTo mileageAndOilWearTo = new MileageAndOilWearTo();
        mileageAndOilWearTo.setCarId(carId);
        mileageAndOilWearTo.setStarttime(starttime);
        mileageAndOilWearTo.setEndtime(endtime);
        try {
            MileageAndOilWearVo mileageAndOilWearVo = carTrackService.mileageAndOilWear(mileageAndOilWearTo);
            oilMassSum = mileageAndOilWearVo.getOilWear();
            mileageSum = mileageAndOilWearVo.getTotalMileage();
        } catch (HssException e) {
            e.printStackTrace();
        }
        if (oilMassSum.compareTo(BigDecimal.ZERO) != 0 && mileageSum.compareTo(BigDecimal.ZERO) != 0) {
            consumptionPer = oilMassSum.divide(mileageSum, 5, BigDecimal.ROUND_HALF_UP);
        }
        map.put("oilMassSum", oilMassSum);
        map.put("mileageSum", mileageSum);
        map.put("consumptionPer", consumptionPer);

//        log.info("开始时间{}", params.get("starttime"));
//        log.info("结束时间{}", params.get("endtime"));
        log.info("总油耗{}", oilMassSum);
        log.info("总里程数{}", mileageSum);
        log.info("平均值{}", consumptionPer);
        return map;
    }


    /**
     * @param targetId
     * @param model(推送类型 1事件2报警3违规)
     * @param sysname
     * @param alarmTypeName
     */
    private void sendAlarm(TlEquip equip, TlFacilities facilities, TlThreshold threshold, String targetId, Integer model, String sysname, String alarmTypeName) {
        QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        List<SysUserRole> sysUserRoleList = sysUserRoleMapper.selectList(sysUserRoleQueryWrapper);
        Map<String, List<SysUserRole>> sysUserRoleMap = sysUserRoleList.stream().collect(Collectors.groupingBy(SysUserRole::getUserid));

        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        List<SysRole> sysRoleList = sysRoleMapper.selectList(sysRoleQueryWrapper);
        Map<String, SysRole> sysRoleMap = sysRoleList.stream().collect(Collectors.groupingBy(SysRole::getId, Collectors.collectingAndThen(toList(), values -> values.get(0))));

        String remindKey = AlarmUtils.changeCarAlarmName(sysname);
        JSONObject alarmJson = new JSONObject();
        alarmJson.put("model", model);
        JSONObject detailJson = new JSONObject();
        detailJson.put("id", targetId);
        detailJson.put("remindKey", remindKey);
        detailJson.put("happenTime", DateUtil.formatDateTime(new Date()));
        detailJson.put("lng", facilities.getFacladdr() != null ? facilities.getFacladdr().split(",")[0] : "");
        detailJson.put("lat", facilities.getFacladdr() != null ? facilities.getFacladdr().split(",")[1] : "");
        detailJson.put("address", facilities.getFacladdrdetail());
        detailJson.put("pic", facilities.getFileurl());
        detailJson.put("typeId", threshold.getFaclitypename());
        detailJson.put("typeName", sysname);
        detailJson.put("authorId", facilities.getId());
        detailJson.put("authorName", facilities.getFaclname());
        detailJson.put("authorType", "facl");
        alarmJson.put("detail", detailJson);
        TlFacilities tlFacilities = tlFacilitiesMapper.selectById(facilities.getId());
        WebSocketUtils.sendMessageToOne(alarmJson.toString(), tlFacilities.getPrincipal());

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().notIn(User::getUid, tlFacilities.getPrincipal());
        List<User> userList = userMapper.selectList(userQueryWrapper);
        for (User user : userList) {
            JSONObject alarmJson1 = new JSONObject();
            alarmJson1.put("model", model);
            JSONObject detailJson1 = new JSONObject();
            detailJson1.put("id", targetId);
            detailJson1.put("remindKey", remindKey);
            detailJson1.put("happenTime", DateUtil.formatDateTime(new Date()));
            detailJson1.put("lng", facilities.getFacladdr() != null ? facilities.getFacladdr().split(",")[0] : "");
            detailJson1.put("lat", facilities.getFacladdr() != null ? facilities.getFacladdr().split(",")[1] : "");
            detailJson1.put("address", facilities.getFacladdrdetail());
            detailJson1.put("pic", facilities.getFileurl());
            detailJson1.put("typeId", threshold.getFaclitypename());
            detailJson1.put("typeName", sysname);
            detailJson1.put("authorId", facilities.getId());
            detailJson1.put("authorName", facilities.getFaclname());
            detailJson1.put("authorType", "facl");
            alarmJson1.put("detail", detailJson1);
            List<SysUserRole> sysUserRoleList1 = sysUserRoleMap.get(user.getUid());
            if (null != sysUserRoleList1) {
                for (SysUserRole sysUserRole : sysUserRoleList1) {
                    SysRole sysRole = sysRoleMap.get(sysUserRole.getRoleid());
                    if (null != sysRole) {
                        if (sysRole.getRoleName().equals("管理员")) {
                            WebSocketUtils.sendMessageToOne(alarmJson1.toString(), sysUserRole.getUserid());
                        }
                    }
                }
            }
        }
    }

    public AbnormalResult saveAlarmSheshi(TlEquip equip, TlFacilities facilities, TlThreshold threshold, Date alarmStartTime, Date alarmEndTime, BigDecimal value, String gasType) {
        String day = DateUtil.formatDate(alarmStartTime);
        AlarmSheshi alarmSheshi = RedisUtil.get(FacilitiesAlarmTypeNameLastOneKeyToday.token, facilities.getId() + "_" + threshold.getSysname() + "_" + day, AlarmSheshi.class);
        if (Objects.isNull(alarmSheshi)) {
            String startTime = AttributeUtils.timeCompletion(day, 's');
            String endTime = AttributeUtils.timeCompletion(day, 'e');

            QueryWrapper<AlarmSheshi> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(AlarmSheshi::getSheshiId, facilities.getId());
            queryWrapper.lambda().eq(AlarmSheshi::getAlarmTypeName, threshold.getSysname());
            queryWrapper.lambda().between(AlarmSheshi::getAlarmTime, startTime, endTime);
            queryWrapper.lambda().orderByDesc(AlarmSheshi::getAlarmTime);
            queryWrapper.lambda().last(" LIMIT 1");
            alarmSheshi = alarmSheshiMapper.selectOne(queryWrapper);
        }

        if (Objects.nonNull(alarmSheshi)) {
            //获取基数天数和检测时间间隔
            //聚合时间(分钟)
            int polymerizationtime = 0;
            if (Objects.nonNull(threshold.getPolymerizationtime())) {
                polymerizationtime = threshold.getPolymerizationtime();
            }
            Date date1 = new Date(alarmStartTime.getTime() - 1000 * 60 * polymerizationtime);
            if (date1.compareTo(alarmSheshi.getAlarmEndTime()) > 0) {
                alarmSheshi = null;
            }
        }

        AbnormalResult abnormalResult = new AbnormalResult();
        if (Objects.nonNull(alarmSheshi)) {
            //过滤掉之前的时间
            if (alarmEndTime.compareTo(alarmSheshi.getAlarmEndTime()) <= 0) {
                return abnormalResult;
            }

            abnormalResult = updateFacilities(alarmSheshi, alarmEndTime, value);
        }
        if (1 != abnormalResult.getIskeep()) {
            abnormalResult = insertFacilities(facilities, threshold, alarmStartTime, alarmEndTime, value, gasType);
        }
        return abnormalResult;
    }

    /**
     * 更新设施报警信息
     *
     * @param facilities
     * @param threshold
     * @param alarmStartTime
     * @param alarmEndTime
     * @return
     */
    private AbnormalResult insertFacilities(TlFacilities facilities, TlThreshold threshold, Date alarmStartTime, Date alarmEndTime, BigDecimal value, String gasType) {
        AbnormalResult abnormalResult = new AbnormalResult();
        String day = DateUtil.formatDate(alarmStartTime);
        AlarmSheshi alarmSheshi1 = RedisUtil.get(FacilitiesAlarmTypeNameLastOneKeyToday.token, facilities.getId() + "_" + threshold.getSysname() + "_" + day, AlarmSheshi.class);
        if (Objects.nonNull(alarmSheshi1) && alarmSheshi1.getAlarmTime().compareTo(alarmEndTime) == 0) {
            abnormalResult.setMessage(alarmSheshi1.getContent());
            return abnormalResult;
        }

        AlarmSheshi alarmSheshi = new AlarmSheshi();
        alarmSheshi.setSheshiId(facilities.getId());
        alarmSheshi.setSheshiName(facilities.getFaclname());
        alarmSheshi.setDepId(facilities.getFacldeptid());
        alarmSheshi.setDepName(facilities.getFacldeptname());
        alarmSheshi.setAlarmTypeId(threshold.getId());
        alarmSheshi.setAlarmTypeName(threshold.getSysname());
        if (null != facilities.getFacladdr()) {
            String[] adds = facilities.getFacladdr().split(",");
            alarmSheshi.setLng(adds[0]);
            alarmSheshi.setLat(adds[1]);
        }
        alarmSheshi.setAddress(facilities.getFacladdrdetail());
        alarmSheshi.setAlarmTime(alarmEndTime);
        if ("开盖报警".equals(threshold.getSysname()) || "水位超限".equals(threshold.getSysname())) {
            alarmSheshi.setContent(threshold.getSysname() + ", 持续时长1s");
        } else if ("烟雾报警".equals(threshold.getSysname())) {
            alarmSheshi.setContent("烟雾报警时长3s，报警最高浓度为" + value + "ppm");
        } else {
            alarmSheshi.setContent(threshold.getSysname() + "时长10s，报警最高浓度为" + value + "ppm");
        }
        alarmSheshi.setCreateTime(alarmEndTime);
        alarmSheshi.setAlarmStartTime(alarmStartTime);
        alarmSheshi.setAlarmEndTime(alarmEndTime);
        alarmSheshi.setAlarmValue(value);
        alarmSheshi.setGasType(gasType);
        //查询设施类型
        TlFacilities tlFacilities = tlFacilitiesMapper.selectById(facilities.getId());
        if (Objects.nonNull(tlFacilities) && StringUtils.isNotEmpty(tlFacilities.getFacltypeid())) {
            alarmSheshi.setFacltypeid(tlFacilities.getFacltypeid());
            alarmSheshi.setFacltypename(tlFacilities.getFacltypename());
            alarmSheshi.setFacltypeitemid(tlFacilities.getFacltypeitemid());
            alarmSheshi.setFacltypeitemname(tlFacilities.getFacltypeitemname());
        }

        int insert = alarmSheshiMapper.insert(alarmSheshi);
        if (insert > 0) {
            abnormalResult.setIskeep(2);
        }

        RedisUtil.set(FacilitiesAlarmTypeNameLastOneKeyToday.token, alarmSheshi.getSheshiId() + "_" + alarmSheshi.getAlarmTypeName() + "_" + day, alarmSheshi);

        abnormalResult.setId(alarmSheshi.getAlarmSheshiId());
        abnormalResult.setMessage(alarmSheshi.getContent());
        return abnormalResult;
    }

    private AbnormalResult saveCarViolation(KfkHandleParam kfkHandleParam, WorkRuleItem workRuleItem, Date alarmStartTime) {
        String today = DateUtil.formatDate(alarmStartTime);
        CarViolation carViolation = RedisUtil.get(CarViolationTypeNameLastOneKeyToday.token, kfkHandleParam.getCarId() + "_" + workRuleItem.getSysName() + "_" + today, CarViolation.class);
        if (Objects.isNull(carViolation)) {
            String day = DateUtil.formatDate(new Date());
            String startTime = AttributeUtils.timeCompletion(day, 's');
            String endTime = AttributeUtils.timeCompletion(day, 'e');

            QueryWrapper<CarViolation> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(CarViolation::getCarId, kfkHandleParam.getCarId());
            queryWrapper.lambda().eq(CarViolation::getRuleTypeName, workRuleItem.getSysName());
            queryWrapper.lambda().between(CarViolation::getTime, startTime, endTime);
            queryWrapper.lambda().orderByDesc(CarViolation::getTime);
            queryWrapper.lambda().last(" LIMIT 1");
            carViolation = carViolationMapper.selectOne(queryWrapper);
        }

        if (Objects.nonNull(carViolation)) {
            //获取基数天数和检测时间间隔
            //聚合时间(分钟)
            int polymerizationtime = 0;
            if (Objects.nonNull(workRuleItem.getPolymerizationtime())) {
                polymerizationtime = workRuleItem.getPolymerizationtime();
            }
            Date date1 = new Date(alarmStartTime.getTime() - 1000 * 60 * polymerizationtime);
            if (date1.compareTo(carViolation.getViolationEndTime()) > 0) {
                carViolation = null;
            }
        }

        AbnormalResult abnormalResult = new AbnormalResult();
        if (Objects.nonNull(carViolation)) {
            //过滤掉之前的时间
            if (kfkHandleParam.getLocationDate().compareTo(carViolation.getViolationEndTime()) <= 0) {
                return abnormalResult;
            }

            abnormalResult = updateCarViolation(kfkHandleParam, carViolation);
        }
        if (1 != abnormalResult.getIskeep()) {
            abnormalResult = insertCarViolation(kfkHandleParam, workRuleItem, alarmStartTime);
        }
        return abnormalResult;
    }

    //获取两点相差秒数
    public Integer getTwoPointDifferTime(CarTrack preCarTrack, CarTrack currentCarTrack) {
        Date preDate = preCarTrack.getTimestamp();
        Date currentDate = currentCarTrack.getTimestamp();
        Long secondDiffer = DateUtil.between(preDate, currentDate, DateUnit.SECOND);
        return secondDiffer.intValue();
    }

    /**
     * 校验人或车是否在应急
     *
     * @param name 人的名称 或 车的车牌号
     * @param type 类型: 人 emp ; 车 car
     * @param date 当前时间
     * @return
     */
    public boolean isEmergency(String name, String type, Date date) {
        QueryWrapper<TlEmergentPlan> tlEmergentPlanQueryWrapper = new QueryWrapper<>();
        if ("emp".equals(type)) {
            tlEmergentPlanQueryWrapper.lambda().like(TlEmergentPlan::getAskemp, name);
        }
        if ("car".equals(type)) {
            tlEmergentPlanQueryWrapper.lambda().like(TlEmergentPlan::getAskcar, name);
        }
        tlEmergentPlanQueryWrapper.lambda().le(TlEmergentPlan::getStarttime, date);
        tlEmergentPlanQueryWrapper.lambda().ge(TlEmergentPlan::getEndtime, date);
        List<TlEmergentPlan> tlEmergentPlanList = tlEmergentPlanMapper.selectList(tlEmergentPlanQueryWrapper);
        if (Objects.nonNull(tlEmergentPlanList) && tlEmergentPlanList.size() > 0) {
            return true;
        } else {
            return false;
        }
    }
}
